1515#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
1516#define _CRT_SECURE_NO_WARNINGS
1519#ifndef IMGUI_DEFINE_MATH_OPERATORS
1520#define IMGUI_DEFINE_MATH_OPERATORS
1524#ifndef IMGUI_DISABLE
1525#include "imgui_internal.h"
1533#if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && \
1534 !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
1535#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
1539#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && \
1540 defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && \
1541 defined(IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
1542#define IMGUI_DISABLE_WIN32_FUNCTIONS
1544#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
1545#ifndef WIN32_LEAN_AND_MEAN
1546#define WIN32_LEAN_AND_MEAN
1556#if defined(WINAPI_FAMILY) && ((defined(WINAPI_FAMILY_APP) && WINAPI_FAMILY == WINAPI_FAMILY_APP) || \
1557 (defined(WINAPI_FAMILY_GAMES) && WINAPI_FAMILY == WINAPI_FAMILY_GAMES))
1559#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
1560#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
1561#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
1566#if defined(__APPLE__)
1567#include <TargetConditionals.h>
1572#pragma warning(disable : 4127)
1575#if defined(_MSC_VER) && _MSC_VER >= 1922
1576#pragma warning(disable : 5054)
1578#pragma warning(disable : 26451)
1589#if defined(__clang__)
1590#if __has_warning("-Wunknown-warning-option")
1591#pragma clang diagnostic ignored \
1592 "-Wunknown-warning-option"
1596#pragma clang diagnostic ignored "-Wunknown-pragmas"
1597#pragma clang diagnostic ignored \
1599#pragma clang diagnostic ignored "-Wfloat-equal"
1601#pragma clang diagnostic ignored \
1603#pragma clang diagnostic ignored \
1604 "-Wformat-nonliteral"
1606#pragma clang diagnostic ignored \
1609#pragma clang diagnostic ignored \
1610 "-Wexit-time-destructors"
1613#pragma clang diagnostic ignored "-Wglobal-constructors"
1615#pragma clang diagnostic ignored "-Wsign-conversion"
1616#pragma clang diagnostic ignored \
1617 "-Wint-to-void-pointer-cast"
1618#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
1620#pragma clang diagnostic ignored \
1621 "-Wdouble-promotion"
1623#pragma clang diagnostic ignored \
1624 "-Wimplicit-int-float-conversion"
1625#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
1626#pragma clang diagnostic ignored "-Wnontrivial-memaccess"
1628#pragma clang diagnostic ignored "-Wswitch-default"
1629#elif defined(__GNUC__)
1632#pragma GCC diagnostic ignored "-Wpragmas"
1633#pragma GCC diagnostic ignored "-Wunused-function"
1634#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
1635#pragma GCC diagnostic ignored "-Wfloat-equal"
1636#pragma GCC diagnostic ignored "-Wformat"
1638#pragma GCC diagnostic ignored \
1639 "-Wdouble-promotion"
1640#pragma GCC diagnostic ignored "-Wconversion"
1641#pragma GCC diagnostic ignored "-Wformat-nonliteral"
1642#pragma GCC diagnostic ignored "-Wstrict-overflow"
1644#pragma GCC diagnostic ignored \
1647#pragma GCC diagnostic ignored \
1652#define IMGUI_DEBUG_NAV_SCORING \
1655#define IMGUI_DEBUG_NAV_RECTS 0
1659static const float NAV_WINDOWING_HIGHLIGHT_DELAY =
1661static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f;
1662static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f;
1663static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER =
1665static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER =
1670static const ImVec2 TOOLTIP_DEFAULT_OFFSET_MOUSE =
ImVec2(16, 10);
1671static const ImVec2 TOOLTIP_DEFAULT_OFFSET_TOUCH =
ImVec2(0, -20);
1672static const ImVec2 TOOLTIP_DEFAULT_PIVOT_TOUCH =
ImVec2(0.5f, 1.0f);
1675static const float DOCKING_TRANSPARENT_PAYLOAD_ALPHA =
1683static ImGuiWindow *CreateNewWindow(
const char *name, ImGuiWindowFlags flags);
1696static const char *Platform_GetClipboardTextFn_DefaultImpl(
ImGuiContext *ctx);
1697static void Platform_SetClipboardTextFn_DefaultImpl(
ImGuiContext *ctx,
const char *text);
1699static bool Platform_OpenInShellFn_DefaultImpl(
ImGuiContext *ctx,
const char *path);
1704static void ItemHandleShortcut(ImGuiID
id);
1707static int FindWindowFocusIndex(
ImGuiWindow *window);
1708static void UpdateWindowInFocusOrderList(
ImGuiWindow *window,
bool just_created, ImGuiWindowFlags new_flags);
1711static void NavUpdate();
1712static void NavUpdateWindowing();
1713static void NavUpdateWindowingApplyFocus(
ImGuiWindow *window);
1714static void NavUpdateWindowingOverlay();
1715static void NavUpdateCancelRequest();
1716static void NavUpdateCreateMoveRequest();
1717static void NavUpdateCreateTabbingRequest();
1718static float NavUpdatePageUpPageDown();
1719static inline void NavUpdateAnyRequestFlag();
1720static void NavUpdateCreateWrappingRequest();
1721static void NavEndFrame();
1724static void NavProcessItem();
1725static void NavProcessItemForTabbingRequest(ImGuiID
id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags);
1726static ImGuiInputSource NavCalcPreferredRefPosSource();
1727static ImVec2 NavCalcPreferredRefPos();
1728static void NavSaveLastChildNavWindowIntoParent(
ImGuiWindow *nav_window);
1730static void NavRestoreLayer(ImGuiNavLayer layer);
1733static void ErrorCheckNewFrameSanityChecks();
1734static void ErrorCheckEndFrameSanityChecks();
1735#ifndef IMGUI_DISABLE_DEBUG_TOOLS
1736static void UpdateDebugToolItemPicker();
1737static void UpdateDebugToolStackQueries();
1738static void UpdateDebugToolFlashStyleColor();
1742static void UpdateKeyboardInputs();
1743static void UpdateMouseInputs();
1744static void UpdateMouseWheel();
1748static void UpdateSettings();
1749static int UpdateWindowManualResize(
ImGuiWindow *window,
const ImVec2 &size_auto_fit,
int *border_hovered,
1750 int *border_held,
int resize_grip_count, ImU32 resize_grip_col[4],
1751 const ImRect &visibility_rect);
1752static void RenderWindowOuterBorders(
ImGuiWindow *window);
1753static void RenderWindowDecorations(
ImGuiWindow *window,
const ImRect &title_bar_rect,
bool title_bar_is_highlight,
1754 bool handle_borders_and_resize_grips,
int resize_grip_count,
1755 const ImU32 resize_grip_col[4],
float resize_grip_draw_size);
1756static void RenderWindowTitleBarContents(
ImGuiWindow *window,
const ImRect &title_bar_rect,
const char *name,
1758static void RenderDimmedBackgroundBehindWindow(
ImGuiWindow *window, ImU32 col);
1759static void RenderDimmedBackgrounds();
1761static void SetLastItemDataForChildWindowItem(
ImGuiWindow *window,
const ImRect &rect);
1764const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID =
1768 const ImVec2 &size, ImGuiViewportFlags flags);
1770static void UpdateViewportsNewFrame();
1771static void UpdateViewportsEndFrame();
1772static void WindowSelectViewport(
ImGuiWindow *window);
1775static bool UpdateTryMergeWindowIntoHostViewports(
ImGuiWindow *window);
1776static bool GetWindowAlwaysWantOwnViewport(
ImGuiWindow *window);
1777static int FindPlatformMonitorForPos(
const ImVec2 &pos);
1778static int FindPlatformMonitorForRect(
const ImRect &r);
1779static void UpdateViewportPlatformMonitor(
ImGuiViewportP *viewport);
1823#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
1824static void *MallocWrapper(
size_t size,
void *user_data)
1826 IM_UNUSED(user_data);
1827 return malloc(size);
1829static void FreeWrapper(
void *ptr,
void *user_data)
1831 IM_UNUSED(user_data);
1835static void *MallocWrapper(
size_t size,
void *user_data)
1837 IM_UNUSED(user_data);
1842static void FreeWrapper(
void *ptr,
void *user_data)
1844 IM_UNUSED(user_data);
1849static ImGuiMemAllocFunc GImAllocatorAllocFunc = MallocWrapper;
1850static ImGuiMemFreeFunc GImAllocatorFreeFunc = FreeWrapper;
1851static void *GImAllocatorUserData = NULL;
1857ImGuiStyle::ImGuiStyle()
1862 WindowPadding =
ImVec2(8, 8);
1863 WindowRounding = 0.0f;
1867 WindowBorderHoverPadding =
1870 WindowMinSize =
ImVec2(32, 32);
1871 WindowTitleAlign =
ImVec2(0.0f, 0.5f);
1872 WindowMenuButtonPosition = ImGuiDir_Left;
1874 ChildRounding = 0.0f;
1877 PopupRounding = 0.0f;
1878 PopupBorderSize = 1.0f;
1880 FramePadding =
ImVec2(4, 3);
1885 ItemSpacing =
ImVec2(8, 4);
1886 ItemInnerSpacing =
ImVec2(4, 4);
1888 CellPadding =
ImVec2(4, 2);
1890 TouchExtraPadding =
ImVec2(0, 0);
1895 ColumnsMinSpacing = 6.0f;
1896 ScrollbarSize = 14.0f;
1897 ScrollbarRounding = 9.0f;
1898 GrabMinSize = 12.0f;
1899 GrabRounding = 0.0f;
1900 LogSliderDeadzone = 4.0f;
1901 ImageBorderSize = 0.0f;
1903 TabBorderSize = 0.0f;
1904 TabCloseButtonMinWidthSelected =
1906 TabCloseButtonMinWidthUnselected =
1909 TabBarBorderSize = 1.0f;
1910 TabBarOverlineSize = 1.0f;
1911 TableAngledHeadersAngle =
1912 35.0f * (IM_PI / 180.0f);
1913 TableAngledHeadersTextAlign =
ImVec2(0.5f, 0.0f);
1914 ColorButtonPosition =
1916 ButtonTextAlign =
ImVec2(0.5f, 0.5f);
1917 SelectableTextAlign =
1920 SeparatorTextBorderSize = 3.0f;
1921 SeparatorTextAlign =
1923 SeparatorTextPadding =
1926 DisplayWindowPadding =
ImVec2(19, 19);
1928 DisplaySafeAreaPadding =
ImVec2(3, 3);
1930 DockingSeparatorSize = 2.0f;
1933 AntiAliasedLines =
true;
1934 AntiAliasedLinesUseTex =
true;
1936 AntiAliasedFill =
true;
1937 CurveTessellationTol =
1940 CircleTessellationMaxError =
1945 HoverStationaryDelay =
1949 HoverDelayNormal = 0.40f;
1950 HoverFlagsForTooltipMouse =
1951 ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort |
1952 ImGuiHoveredFlags_AllowWhenDisabled;
1954 HoverFlagsForTooltipNav =
1955 ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal |
1956 ImGuiHoveredFlags_AllowWhenDisabled;
1960 ImGui::StyleColorsDark(
this);
1967void ImGuiStyle::ScaleAllSizes(
float scale_factor)
1969 WindowPadding = ImTrunc(WindowPadding * scale_factor);
1970 WindowRounding = ImTrunc(WindowRounding * scale_factor);
1971 WindowMinSize = ImTrunc(WindowMinSize * scale_factor);
1972 WindowBorderHoverPadding = ImTrunc(WindowBorderHoverPadding * scale_factor);
1973 ChildRounding = ImTrunc(ChildRounding * scale_factor);
1974 PopupRounding = ImTrunc(PopupRounding * scale_factor);
1975 FramePadding = ImTrunc(FramePadding * scale_factor);
1976 FrameRounding = ImTrunc(FrameRounding * scale_factor);
1977 ItemSpacing = ImTrunc(ItemSpacing * scale_factor);
1978 ItemInnerSpacing = ImTrunc(ItemInnerSpacing * scale_factor);
1979 CellPadding = ImTrunc(CellPadding * scale_factor);
1980 TouchExtraPadding = ImTrunc(TouchExtraPadding * scale_factor);
1981 IndentSpacing = ImTrunc(IndentSpacing * scale_factor);
1982 ColumnsMinSpacing = ImTrunc(ColumnsMinSpacing * scale_factor);
1983 ScrollbarSize = ImTrunc(ScrollbarSize * scale_factor);
1984 ScrollbarRounding = ImTrunc(ScrollbarRounding * scale_factor);
1985 GrabMinSize = ImTrunc(GrabMinSize * scale_factor);
1986 GrabRounding = ImTrunc(GrabRounding * scale_factor);
1987 LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor);
1988 ImageBorderSize = ImTrunc(ImageBorderSize * scale_factor);
1989 TabRounding = ImTrunc(TabRounding * scale_factor);
1990 TabCloseButtonMinWidthSelected =
1991 (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX)
1992 ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor)
1993 : TabCloseButtonMinWidthSelected;
1994 TabCloseButtonMinWidthUnselected =
1995 (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX)
1996 ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor)
1997 : TabCloseButtonMinWidthUnselected;
1998 TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor);
1999 SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor);
2000 DockingSeparatorSize = ImTrunc(DockingSeparatorSize * scale_factor);
2001 DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor);
2002 DisplaySafeAreaPadding = ImTrunc(DisplaySafeAreaPadding * scale_factor);
2003 MouseCursorScale = ImTrunc(MouseCursorScale * scale_factor);
2009 memset(
this, 0,
sizeof(*
this));
2010 IM_STATIC_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT &&
2011 IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT);
2014 ConfigFlags = ImGuiConfigFlags_None;
2015 BackendFlags = ImGuiBackendFlags_None;
2016 DisplaySize =
ImVec2(-1.0f, -1.0f);
2017 DeltaTime = 1.0f / 60.0f;
2018 IniSavingRate = 5.0f;
2019 IniFilename =
"imgui.ini";
2021 LogFilename =
"imgui_log.txt";
2025 FontGlobalScale = 1.0f;
2027 FontAllowUserScaling =
false;
2028 DisplayFramebufferScale =
ImVec2(1.0f, 1.0f);
2031 ConfigNavSwapGamepadButtons =
false;
2032 ConfigNavMoveSetMousePos =
false;
2033 ConfigNavCaptureKeyboard =
true;
2034 ConfigNavEscapeClearFocusItem =
true;
2035 ConfigNavEscapeClearFocusWindow =
false;
2036 ConfigNavCursorVisibleAuto =
true;
2037 ConfigNavCursorVisibleAlways =
false;
2040 ConfigDockingNoSplit =
false;
2041 ConfigDockingWithShift =
false;
2042 ConfigDockingAlwaysTabBar =
false;
2043 ConfigDockingTransparentPayload =
false;
2046 ConfigViewportsNoAutoMerge =
false;
2047 ConfigViewportsNoTaskBarIcon =
false;
2048 ConfigViewportsNoDecoration =
true;
2049 ConfigViewportsNoDefaultParent =
false;
2052 MouseDrawCursor =
false;
2054 ConfigMacOSXBehaviors =
true;
2056 ConfigMacOSXBehaviors =
false;
2058 ConfigInputTrickleEventQueue =
true;
2059 ConfigInputTextCursorBlink =
true;
2060 ConfigInputTextEnterKeepActive =
false;
2061 ConfigDragClickToInputText =
false;
2062 ConfigWindowsResizeFromEdges =
true;
2063 ConfigWindowsMoveFromTitleBarOnly =
false;
2064 ConfigWindowsCopyContentsWithCtrlC =
false;
2065 ConfigScrollbarScrollByPage =
true;
2066 ConfigMemoryCompactTimer = 60.0f;
2067 ConfigDebugIsDebuggerPresent =
false;
2068 ConfigDebugHighlightIdConflicts =
true;
2069 ConfigDebugHighlightIdConflictsShowItemPicker =
true;
2070 ConfigDebugBeginReturnValueOnce =
false;
2071 ConfigDebugBeginReturnValueLoop =
false;
2073 ConfigErrorRecovery =
true;
2074 ConfigErrorRecoveryEnableAssert =
true;
2075 ConfigErrorRecoveryEnableDebugLog =
true;
2076 ConfigErrorRecoveryEnableTooltip =
true;
2079 MouseDoubleClickTime = 0.30f;
2080 MouseDoubleClickMaxDist = 6.0f;
2081 MouseDragThreshold = 6.0f;
2082 KeyRepeatDelay = 0.275f;
2083 KeyRepeatRate = 0.050f;
2087 BackendPlatformName = BackendRendererName = NULL;
2088 BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
2091 MousePos =
ImVec2(-FLT_MAX, -FLT_MAX);
2092 MousePosPrev =
ImVec2(-FLT_MAX, -FLT_MAX);
2093 MouseSource = ImGuiMouseSource_Mouse;
2094 for (
int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++)
2095 MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
2096 for (
int i = 0; i < IM_ARRAYSIZE(KeysData); i++)
2098 KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f;
2100 AppAcceptingEvents =
true;
2107void ImGuiIO::AddInputCharacter(
unsigned int c)
2109 IM_ASSERT(Ctx != NULL);
2111 if (c == 0 || !AppAcceptingEvents)
2115 e.Type = ImGuiInputEventType_Text;
2116 e.Source = ImGuiInputSource_Keyboard;
2117 e.EventId = g.InputEventsNextEventId++;
2119 g.InputEventsQueue.push_back(e);
2124void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
2126 if ((c == 0 && InputQueueSurrogate == 0) || !AppAcceptingEvents)
2129 if ((c & 0xFC00) == 0xD800)
2131 if (InputQueueSurrogate != 0)
2132 AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID);
2133 InputQueueSurrogate = c;
2138 if (InputQueueSurrogate != 0)
2140 if ((c & 0xFC00) != 0xDC00)
2142 AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID);
2146#if IM_UNICODE_CODEPOINT_MAX == 0xFFFF
2147 cp = IM_UNICODE_CODEPOINT_INVALID;
2149 cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000);
2153 InputQueueSurrogate = 0;
2155 AddInputCharacter((
unsigned)cp);
2158void ImGuiIO::AddInputCharactersUTF8(
const char *utf8_chars)
2160 if (!AppAcceptingEvents)
2162 while (*utf8_chars != 0)
2165 utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
2166 AddInputCharacter(c);
2171void ImGuiIO::ClearEventsQueue()
2173 IM_ASSERT(Ctx != NULL);
2175 g.InputEventsQueue.clear();
2179void ImGuiIO::ClearInputKeys()
2182 for (
int key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key++)
2184 if (ImGui::IsMouseKey((ImGuiKey)key))
2186 ImGuiKeyData *key_data = &g.IO.KeysData[key - ImGuiKey_NamedKey_BEGIN];
2187 key_data->Down =
false;
2188 key_data->DownDuration = -1.0f;
2189 key_data->DownDurationPrev = -1.0f;
2191 KeyCtrl = KeyShift = KeyAlt = KeySuper =
false;
2192 KeyMods = ImGuiMod_None;
2193 InputQueueCharacters.resize(0);
2196void ImGuiIO::ClearInputMouse()
2198 for (ImGuiKey key = ImGuiKey_Mouse_BEGIN; key < ImGuiKey_Mouse_END; key = (ImGuiKey)(key + 1))
2200 ImGuiKeyData *key_data = &KeysData[key - ImGuiKey_NamedKey_BEGIN];
2201 key_data->Down =
false;
2202 key_data->DownDuration = -1.0f;
2203 key_data->DownDurationPrev = -1.0f;
2205 MousePos =
ImVec2(-FLT_MAX, -FLT_MAX);
2206 for (
int n = 0; n < IM_ARRAYSIZE(MouseDown); n++)
2208 MouseDown[n] =
false;
2209 MouseDownDuration[n] = MouseDownDurationPrev[n] = -1.0f;
2211 MouseWheel = MouseWheelH = 0.0f;
2216#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
2217void ImGuiIO::ClearInputCharacters()
2219 InputQueueCharacters.resize(0);
2226 for (
int n = g.InputEventsQueue.Size - 1; n >= 0; n--)
2229 if (e->Type != type)
2231 if (type == ImGuiInputEventType_Key && e->Key.Key != arg)
2233 if (type == ImGuiInputEventType_MouseButton && e->MouseButton.Button != arg)
2247void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key,
bool down,
float analog_value)
2251 IM_ASSERT(Ctx != NULL);
2252 if (key == ImGuiKey_None || !AppAcceptingEvents)
2255 IM_ASSERT(ImGui::IsNamedKeyOrMod(key));
2257 IM_ASSERT(ImGui::IsAliasKey(key) ==
false);
2261 if (g.IO.ConfigMacOSXBehaviors)
2263 if (key == ImGuiMod_Super)
2265 key = ImGuiMod_Ctrl;
2267 else if (key == ImGuiMod_Ctrl)
2269 key = ImGuiMod_Super;
2271 else if (key == ImGuiKey_LeftSuper)
2273 key = ImGuiKey_LeftCtrl;
2275 else if (key == ImGuiKey_RightSuper)
2277 key = ImGuiKey_RightCtrl;
2279 else if (key == ImGuiKey_LeftCtrl)
2281 key = ImGuiKey_LeftSuper;
2283 else if (key == ImGuiKey_RightCtrl)
2285 key = ImGuiKey_RightSuper;
2290 const ImGuiInputEvent *latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_Key, (
int)key);
2291 const ImGuiKeyData *key_data = ImGui::GetKeyData(&g, key);
2292 const bool latest_key_down = latest_event ? latest_event->Key.Down : key_data->Down;
2293 const float latest_key_analog = latest_event ? latest_event->Key.AnalogValue : key_data->AnalogValue;
2294 if (latest_key_down == down && latest_key_analog == analog_value)
2299 e.Type = ImGuiInputEventType_Key;
2300 e.Source = ImGui::IsGamepadKey(key) ? ImGuiInputSource_Gamepad : ImGuiInputSource_Keyboard;
2301 e.EventId = g.InputEventsNextEventId++;
2304 e.Key.AnalogValue = analog_value;
2305 g.InputEventsQueue.push_back(e);
2308void ImGuiIO::AddKeyEvent(ImGuiKey key,
bool down)
2310 if (!AppAcceptingEvents)
2312 AddKeyAnalogEvent(key, down, down ? 1.0f : 0.0f);
2319void ImGuiIO::SetKeyEventNativeData(ImGuiKey key,
int native_keycode,
int native_scancode,
int native_legacy_index)
2321 if (key == ImGuiKey_None)
2323 IM_ASSERT(ImGui::IsNamedKey(key));
2324 IM_ASSERT(native_legacy_index == -1 || ImGui::IsLegacyKey((ImGuiKey)native_legacy_index));
2326 IM_UNUSED(native_keycode);
2327 IM_UNUSED(native_scancode);
2328 IM_UNUSED(native_legacy_index);
2333void ImGuiIO::SetAppAcceptingEvents(
bool accepting_events)
2335 AppAcceptingEvents = accepting_events;
2339void ImGuiIO::AddMousePosEvent(
float x,
float y)
2341 IM_ASSERT(Ctx != NULL);
2343 if (!AppAcceptingEvents)
2347 ImVec2 pos((x > -FLT_MAX) ? ImFloor(x) : x, (y > -FLT_MAX) ? ImFloor(y) : y);
2350 const ImGuiInputEvent *latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_MousePos);
2351 const ImVec2 latest_pos =
2352 latest_event ?
ImVec2(latest_event->MousePos.PosX, latest_event->MousePos.PosY) : g.IO.MousePos;
2353 if (latest_pos.x == pos.x && latest_pos.y == pos.y)
2357 e.Type = ImGuiInputEventType_MousePos;
2358 e.Source = ImGuiInputSource_Mouse;
2359 e.EventId = g.InputEventsNextEventId++;
2360 e.MousePos.PosX = pos.x;
2361 e.MousePos.PosY = pos.y;
2362 e.MousePos.MouseSource = g.InputEventsNextMouseSource;
2363 g.InputEventsQueue.push_back(e);
2366void ImGuiIO::AddMouseButtonEvent(
int mouse_button,
bool down)
2368 IM_ASSERT(Ctx != NULL);
2370 IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT);
2371 if (!AppAcceptingEvents)
2375 if (ConfigMacOSXBehaviors && mouse_button == 0 && MouseCtrlLeftAsRightClick)
2380 MouseCtrlLeftAsRightClick =
false;
2384 const ImGuiInputEvent *latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_MouseButton, (
int)mouse_button);
2385 const bool latest_button_down = latest_event ? latest_event->MouseButton.Down : g.IO.MouseDown[mouse_button];
2386 if (latest_button_down == down)
2392 if (ConfigMacOSXBehaviors && mouse_button == 0 && down)
2395 FindLatestInputEvent(&g, ImGuiInputEventType_Key, (
int)ImGuiMod_Super);
2396 if (latest_super_event ? latest_super_event->Key.Down : g.IO.KeySuper)
2398 IMGUI_DEBUG_LOG_IO(
"[io] Super+Left Click aliased into Right Click\n");
2399 MouseCtrlLeftAsRightClick =
true;
2400 AddMouseButtonEvent(
2407 e.Type = ImGuiInputEventType_MouseButton;
2408 e.Source = ImGuiInputSource_Mouse;
2409 e.EventId = g.InputEventsNextEventId++;
2410 e.MouseButton.Button = mouse_button;
2411 e.MouseButton.Down = down;
2412 e.MouseButton.MouseSource = g.InputEventsNextMouseSource;
2413 g.InputEventsQueue.push_back(e);
2417void ImGuiIO::AddMouseWheelEvent(
float wheel_x,
float wheel_y)
2419 IM_ASSERT(Ctx != NULL);
2423 if (!AppAcceptingEvents || (wheel_x == 0.0f && wheel_y == 0.0f))
2427 e.Type = ImGuiInputEventType_MouseWheel;
2428 e.Source = ImGuiInputSource_Mouse;
2429 e.EventId = g.InputEventsNextEventId++;
2430 e.MouseWheel.WheelX = wheel_x;
2431 e.MouseWheel.WheelY = wheel_y;
2432 e.MouseWheel.MouseSource = g.InputEventsNextMouseSource;
2433 g.InputEventsQueue.push_back(e);
2439void ImGuiIO::AddMouseSourceEvent(ImGuiMouseSource source)
2441 IM_ASSERT(Ctx != NULL);
2443 g.InputEventsNextMouseSource = source;
2446void ImGuiIO::AddMouseViewportEvent(ImGuiID viewport_id)
2448 IM_ASSERT(Ctx != NULL);
2451 if (!AppAcceptingEvents)
2455 const ImGuiInputEvent *latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_MouseViewport);
2456 const ImGuiID latest_viewport_id =
2457 latest_event ? latest_event->MouseViewport.HoveredViewportID : g.IO.MouseHoveredViewport;
2458 if (latest_viewport_id == viewport_id)
2462 e.Type = ImGuiInputEventType_MouseViewport;
2463 e.Source = ImGuiInputSource_Mouse;
2464 e.MouseViewport.HoveredViewportID = viewport_id;
2465 g.InputEventsQueue.push_back(e);
2468void ImGuiIO::AddFocusEvent(
bool focused)
2470 IM_ASSERT(Ctx != NULL);
2474 const ImGuiInputEvent *latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_Focus);
2475 const bool latest_focused = latest_event ? latest_event->AppFocused.Focused : !g.IO.AppFocusLost;
2476 if (latest_focused == focused || (ConfigDebugIgnoreFocusLoss && !focused))
2480 e.Type = ImGuiInputEventType_Focus;
2481 e.EventId = g.InputEventsNextEventId++;
2482 e.AppFocused.Focused = focused;
2483 g.InputEventsQueue.push_back(e);
2486ImGuiPlatformIO::ImGuiPlatformIO()
2489 memset(
this, 0,
sizeof(*
this));
2490 Platform_LocaleDecimalPoint =
'.';
2498 const ImVec2 &p,
int num_segments)
2500 IM_ASSERT(num_segments > 0);
2503 float p_closest_dist2 = FLT_MAX;
2504 float t_step = 1.0f / (float)num_segments;
2505 for (
int i_step = 1; i_step <= num_segments; i_step++)
2507 ImVec2 p_current = ImBezierCubicCalc(p1, p2, p3, p4, t_step * i_step);
2508 ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p);
2509 float dist2 = ImLengthSqr(p - p_line);
2510 if (dist2 < p_closest_dist2)
2513 p_closest_dist2 = dist2;
2521static void ImBezierCubicClosestPointCasteljauStep(
const ImVec2 &p,
ImVec2 &p_closest,
ImVec2 &p_last,
2522 float &p_closest_dist2,
float x1,
float y1,
float x2,
float y2,
2523 float x3,
float y3,
float x4,
float y4,
float tess_tol,
int level)
2527 float d2 = ((x2 - x4) * dy - (y2 - y4) * dx);
2528 float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
2529 d2 = (d2 >= 0) ? d2 : -d2;
2530 d3 = (d3 >= 0) ? d3 : -d3;
2531 if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
2533 ImVec2 p_current(x4, y4);
2534 ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p);
2535 float dist2 = ImLengthSqr(p - p_line);
2536 if (dist2 < p_closest_dist2)
2539 p_closest_dist2 = dist2;
2543 else if (level < 10)
2545 float x12 = (x1 + x2) * 0.5f, y12 = (y1 + y2) * 0.5f;
2546 float x23 = (x2 + x3) * 0.5f, y23 = (y2 + y3) * 0.5f;
2547 float x34 = (x3 + x4) * 0.5f, y34 = (y3 + y4) * 0.5f;
2548 float x123 = (x12 + x23) * 0.5f, y123 = (y12 + y23) * 0.5f;
2549 float x234 = (x23 + x34) * 0.5f, y234 = (y23 + y34) * 0.5f;
2550 float x1234 = (x123 + x234) * 0.5f, y1234 = (y123 + y234) * 0.5f;
2551 ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123,
2552 x1234, y1234, tess_tol, level + 1);
2553 ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34,
2554 y34, x4, y4, tess_tol, level + 1);
2561 const ImVec2 &p,
float tess_tol)
2563 IM_ASSERT(tess_tol > 0.0f);
2566 float p_closest_dist2 = FLT_MAX;
2567 ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y,
2568 p4.x, p4.y, tess_tol, 0);
2576 float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
2579 float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
2580 if (dot > ab_len_sqr)
2582 return a + ab_dir * dot / ab_len_sqr;
2587 bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
2588 bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
2589 bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
2590 return ((b1 == b2) && (b2 == b3));
2594 float &out_v,
float &out_w)
2599 const float denom = v0.x * v1.y - v1.x * v0.y;
2600 out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
2601 out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
2602 out_u = 1.0f - out_v - out_w;
2607 ImVec2 proj_ab = ImLineClosestPoint(a, b, p);
2608 ImVec2 proj_bc = ImLineClosestPoint(b, c, p);
2609 ImVec2 proj_ca = ImLineClosestPoint(c, a, p);
2610 float dist2_ab = ImLengthSqr(p - proj_ab);
2611 float dist2_bc = ImLengthSqr(p - proj_bc);
2612 float dist2_ca = ImLengthSqr(p - proj_ca);
2613 float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
2627int ImStricmp(
const char *str1,
const char *str2)
2630 while ((d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1)
2638int ImStrnicmp(
const char *str1,
const char *str2,
size_t count)
2641 while (count > 0 && (d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1)
2650void ImStrncpy(
char *dst,
const char *src,
size_t count)
2655 strncpy(dst, src, count - 1);
2659char *ImStrdup(
const char *str)
2661 size_t len = ImStrlen(str);
2662 void *buf = IM_ALLOC(len + 1);
2663 return (
char *)memcpy(buf, (
const void *)str, len + 1);
2666char *ImStrdupcpy(
char *dst,
size_t *p_dst_size,
const char *src)
2668 size_t dst_buf_size = p_dst_size ? *p_dst_size : ImStrlen(dst) + 1;
2669 size_t src_size = ImStrlen(src) + 1;
2670 if (dst_buf_size < src_size)
2673 dst = (
char *)IM_ALLOC(src_size);
2675 *p_dst_size = src_size;
2677 return (
char *)memcpy(dst, (
const void *)src, src_size);
2680const char *ImStrchrRange(
const char *str,
const char *str_end,
char c)
2682 const char *p = (
const char *)ImMemchr(str, (
int)c, str_end - str);
2686int ImStrlenW(
const ImWchar *str)
2696const char *ImStreolRange(
const char *str,
const char *str_end)
2698 const char *p = (
const char *)ImMemchr(str,
'\n', str_end - str);
2699 return p ? p : str_end;
2702const char *ImStrbol(
const char *buf_mid_line,
const char *buf_begin)
2704 IM_ASSERT_PARANOID(buf_mid_line >= buf_begin && buf_mid_line <= buf_begin + ImStrlen(buf_begin));
2705 while (buf_mid_line > buf_begin && buf_mid_line[-1] !=
'\n')
2707 return buf_mid_line;
2710const char *ImStristr(
const char *haystack,
const char *haystack_end,
const char *needle,
const char *needle_end)
2713 needle_end = needle + ImStrlen(needle);
2715 const char un0 = (char)ImToUpper(*needle);
2716 while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
2718 if (ImToUpper(*haystack) == un0)
2720 const char *b = needle + 1;
2721 for (
const char *a = haystack + 1; b < needle_end; a++, b++)
2722 if (ImToUpper(*a) != ImToUpper(*b))
2724 if (b == needle_end)
2734void ImStrTrimBlanks(
char *buf)
2737 while (p[0] ==
' ' || p[0] ==
'\t')
2742 while (p > p_start && (p[-1] ==
' ' || p[-1] ==
'\t'))
2745 memmove(buf, p_start, p - p_start);
2746 buf[p - p_start] = 0;
2749const char *ImStrSkipBlank(
const char *str)
2751 while (str[0] ==
' ' || str[0] ==
'\t')
2760#ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
2766#ifdef IMGUI_USE_STB_SPRINTF
2767#ifndef IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION
2768#define STB_SPRINTF_IMPLEMENTATION
2770#ifdef IMGUI_STB_SPRINTF_FILENAME
2771#include IMGUI_STB_SPRINTF_FILENAME
2773#include "stb_sprintf.h"
2777#if defined(_MSC_VER) && !defined(vsnprintf)
2778#define vsnprintf _vsnprintf
2781int ImFormatString(
char *buf,
size_t buf_size,
const char *fmt, ...)
2784 va_start(args, fmt);
2785#ifdef IMGUI_USE_STB_SPRINTF
2786 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
2788 int w = vsnprintf(buf, buf_size, fmt, args);
2793 if (w == -1 || w >= (
int)buf_size)
2794 w = (int)buf_size - 1;
2799int ImFormatStringV(
char *buf,
size_t buf_size,
const char *fmt, va_list args)
2801#ifdef IMGUI_USE_STB_SPRINTF
2802 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
2804 int w = vsnprintf(buf, buf_size, fmt, args);
2808 if (w == -1 || w >= (
int)buf_size)
2809 w = (int)buf_size - 1;
2815void ImFormatStringToTempBuffer(
const char **out_buf,
const char **out_buf_end,
const char *fmt, ...)
2818 va_start(args, fmt);
2819 ImFormatStringToTempBufferV(out_buf, out_buf_end, fmt, args);
2827void ImFormatStringToTempBufferV(
const char **out_buf,
const char **out_buf_end,
const char *fmt, va_list args)
2830 if (fmt[0] ==
'%' && fmt[1] ==
's' && fmt[2] == 0)
2832 const char *buf = va_arg(args,
const char *);
2838 *out_buf_end = buf + ImStrlen(buf);
2841 else if (fmt[0] ==
'%' && fmt[1] ==
'.' && fmt[2] ==
'*' && fmt[3] ==
's' && fmt[4] == 0)
2843 int buf_len = va_arg(args,
int);
2844 const char *buf = va_arg(args,
const char *);
2848 buf_len = ImMin(buf_len, 6);
2851 *out_buf_end = buf + buf_len;
2855 int buf_len = ImFormatStringV(g.TempBuffer.Data, g.TempBuffer.Size, fmt, args);
2856 *out_buf = g.TempBuffer.Data;
2859 *out_buf_end = g.TempBuffer.Data + buf_len;
2864#ifndef IMGUI_ENABLE_SSE4_2_CRC
2870static const ImU32 GCrc32LookupTable[256] = {
2871#ifdef IMGUI_USE_LEGACY_CRC32_ADLER
2874 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832,
2875 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
2876 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A,
2877 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
2878 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
2879 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
2880 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
2881 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
2882 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4,
2883 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
2884 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
2885 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
2886 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525,
2887 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
2888 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
2889 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
2890 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76,
2891 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
2892 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6,
2893 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
2894 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
2895 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
2896 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7,
2897 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
2898 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
2899 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
2900 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330,
2901 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
2902 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
2905 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 0x8AD958CF,
2906 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 0x105EC76F, 0xE235446C,
2907 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57,
2908 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
2909 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E,
2910 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD,
2911 0x1642AE59, 0xE4292D5A, 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696,
2912 0x6EF07595, 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
2913 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 0x5125DAD3,
2914 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 0xDBFC821C, 0x2997011F,
2915 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 0x61C69362, 0x93AD1061, 0x80FDE395,
2916 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
2917 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312,
2918 0x44694011, 0x5739B3E5, 0xA55230E6, 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE,
2919 0xDDE0EB2A, 0x2F8B6829, 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90,
2920 0x563C5F93, 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
2921 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 0x1871A4D8,
2922 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 0xA24BB5A6, 0x502036A5,
2923 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E,
2924 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
2925 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19,
2926 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8,
2927 0xE52CC12C, 0x1747422F, 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3,
2928 0x9D9E1AE0, 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
2929 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 0xE330A81A,
2930 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 0x69E9F0D5, 0x9B8273D6,
2931 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 0xF36E6F75, 0x0105EC76, 0x12551F82,
2932 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
2933 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
2941ImGuiID ImHashData(
const void *data_p,
size_t data_size, ImGuiID seed)
2944 const unsigned char *data = (
const unsigned char *)data_p;
2945 const unsigned char *data_end = (
const unsigned char *)data_p + data_size;
2946#ifndef IMGUI_ENABLE_SSE4_2_CRC
2947 const ImU32 *crc32_lut = GCrc32LookupTable;
2948 while (data < data_end)
2949 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
2952 while (data + 4 <= data_end)
2954 crc = _mm_crc32_u32(crc, *(ImU32 *)data);
2957 while (data < data_end)
2958 crc = _mm_crc32_u8(crc, *data++);
2970ImGuiID ImHashStr(
const char *data_p,
size_t data_size, ImGuiID seed)
2974 const unsigned char *data = (
const unsigned char *)data_p;
2975#ifndef IMGUI_ENABLE_SSE4_2_CRC
2976 const ImU32 *crc32_lut = GCrc32LookupTable;
2980 while (data_size-- != 0)
2982 unsigned char c = *data++;
2983 if (c ==
'#' && data_size >= 2 && data[0] ==
'#' && data[1] ==
'#')
2985#ifndef IMGUI_ENABLE_SSE4_2_CRC
2986 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
2988 crc = _mm_crc32_u8(crc, c);
2994 while (
unsigned char c = *data++)
2996 if (c ==
'#' && data[0] ==
'#' && data[1] ==
'#')
2998#ifndef IMGUI_ENABLE_SSE4_2_CRC
2999 crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
3001 crc = _mm_crc32_u8(crc, c);
3013#ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
3015ImFileHandle ImFileOpen(
const char *filename,
const char *mode)
3017#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && \
3018 (defined(__MINGW32__) || (!defined(__CYGWIN__) && !defined(__GNUC__)))
3022 const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
3023 const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
3028 wchar_t local_temp_stack[FILENAME_MAX];
3030 if (filename_wsize + mode_wsize > IM_ARRAYSIZE(local_temp_stack))
3031 local_temp_heap.resize(filename_wsize + mode_wsize);
3032 wchar_t *filename_wbuf = local_temp_heap.Data ? local_temp_heap.Data : local_temp_stack;
3033 wchar_t *mode_wbuf = filename_wbuf + filename_wsize;
3034 ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_wbuf, filename_wsize);
3035 ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_wbuf, mode_wsize);
3036 return ::_wfopen(filename_wbuf, mode_wbuf);
3038 return fopen(filename, mode);
3044bool ImFileClose(ImFileHandle f)
3046 return fclose(f) == 0;
3048ImU64 ImFileGetSize(ImFileHandle f)
3050 long off = 0, sz = 0;
3051 return ((off = ftell(f)) != -1 && !fseek(f, 0, SEEK_END) && (sz = ftell(f)) != -1 && !fseek(f, off, SEEK_SET))
3055ImU64 ImFileRead(
void *data, ImU64 sz, ImU64 count, ImFileHandle f)
3057 return fread(data, (
size_t)sz, (
size_t)count, f);
3059ImU64 ImFileWrite(
const void *data, ImU64 sz, ImU64 count, ImFileHandle f)
3061 return fwrite(data, (
size_t)sz, (
size_t)count, f);
3068void *ImFileLoadToMemory(
const char *filename,
const char *mode,
size_t *out_file_size,
int padding_bytes)
3070 IM_ASSERT(filename && mode);
3075 if ((f = ImFileOpen(filename, mode)) == NULL)
3078 size_t file_size = (size_t)ImFileGetSize(f);
3079 if (file_size == (
size_t)-1)
3085 void *file_data = IM_ALLOC(file_size + padding_bytes);
3086 if (file_data == NULL)
3091 if (ImFileRead(file_data, 1, file_size, f) != file_size)
3097 if (padding_bytes > 0)
3098 memset((
void *)(((
char *)file_data) + file_size), 0, (
size_t)padding_bytes);
3102 *out_file_size = file_size;
3111IM_MSVC_RUNTIME_CHECKS_OFF
3116int ImTextCharFromUtf8(
unsigned int *out_char,
const char *in_text,
const char *in_text_end)
3118 static const char lengths[32] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3119 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0};
3120 static const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
3121 static const uint32_t mins[] = {0x400000, 0, 0x80, 0x800, 0x10000};
3122 static const int shiftc[] = {0, 18, 12, 6, 0};
3123 static const int shifte[] = {0, 6, 4, 2, 0};
3124 int len = lengths[*(
const unsigned char *)in_text >> 3];
3125 int wanted = len + (len ? 0 : 1);
3127 if (in_text_end == NULL)
3128 in_text_end = in_text + wanted;
3133 s[0] = in_text + 0 < in_text_end ? in_text[0] : 0;
3134 s[1] = in_text + 1 < in_text_end ? in_text[1] : 0;
3135 s[2] = in_text + 2 < in_text_end ? in_text[2] : 0;
3136 s[3] = in_text + 3 < in_text_end ? in_text[3] : 0;
3139 *out_char = (uint32_t)(s[0] & masks[len]) << 18;
3140 *out_char |= (uint32_t)(s[1] & 0x3f) << 12;
3141 *out_char |= (uint32_t)(s[2] & 0x3f) << 6;
3142 *out_char |= (uint32_t)(s[3] & 0x3f) << 0;
3143 *out_char >>= shiftc[len];
3147 e = (*out_char < mins[len]) << 6;
3148 e |= ((*out_char >> 11) == 0x1b) << 7;
3149 e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8;
3150 e |= (s[1] & 0xc0) >> 2;
3151 e |= (s[2] & 0xc0) >> 4;
3163 wanted = ImMin(wanted, !!s[0] + !!s[1] + !!s[2] + !!s[3]);
3164 *out_char = IM_UNICODE_CODEPOINT_INVALID;
3170int ImTextStrFromUtf8(ImWchar *buf,
int buf_size,
const char *in_text,
const char *in_text_end,
3171 const char **in_text_remaining)
3173 ImWchar *buf_out = buf;
3174 ImWchar *buf_end = buf + buf_size;
3175 while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
3178 in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
3179 *buf_out++ = (ImWchar)c;
3182 if (in_text_remaining)
3183 *in_text_remaining = in_text;
3184 return (
int)(buf_out - buf);
3187int ImTextCountCharsFromUtf8(
const char *in_text,
const char *in_text_end)
3190 while ((!in_text_end || in_text < in_text_end) && *in_text)
3193 in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
3200static inline int ImTextCharToUtf8_inline(
char *buf,
int buf_size,
unsigned int c)
3211 buf[0] = (char)(0xc0 + (c >> 6));
3212 buf[1] = (char)(0x80 + (c & 0x3f));
3219 buf[0] = (char)(0xe0 + (c >> 12));
3220 buf[1] = (char)(0x80 + ((c >> 6) & 0x3f));
3221 buf[2] = (char)(0x80 + ((c) & 0x3f));
3228 buf[0] = (char)(0xf0 + (c >> 18));
3229 buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
3230 buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
3231 buf[3] = (char)(0x80 + ((c) & 0x3f));
3238const char *ImTextCharToUtf8(
char out_buf[5],
unsigned int c)
3240 int count = ImTextCharToUtf8_inline(out_buf, 5, c);
3246int ImTextCountUtf8BytesFromChar(
const char *in_text,
const char *in_text_end)
3248 unsigned int unused = 0;
3249 return ImTextCharFromUtf8(&unused, in_text, in_text_end);
3252static inline int ImTextCountUtf8BytesFromChar(
unsigned int c)
3265int ImTextStrToUtf8(
char *out_buf,
int out_buf_size,
const ImWchar *in_text,
const ImWchar *in_text_end)
3267 char *buf_p = out_buf;
3268 const char *buf_end = out_buf + out_buf_size;
3269 while (buf_p < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
3271 unsigned int c = (
unsigned int)(*in_text++);
3275 buf_p += ImTextCharToUtf8_inline(buf_p, (
int)(buf_end - buf_p - 1), c);
3278 return (
int)(buf_p - out_buf);
3281int ImTextCountUtf8BytesFromStr(
const ImWchar *in_text,
const ImWchar *in_text_end)
3283 int bytes_count = 0;
3284 while ((!in_text_end || in_text < in_text_end) && *in_text)
3286 unsigned int c = (
unsigned int)(*in_text++);
3290 bytes_count += ImTextCountUtf8BytesFromChar(c);
3295const char *ImTextFindPreviousUtf8Codepoint(
const char *in_text_start,
const char *in_text_curr)
3297 while (in_text_curr > in_text_start)
3300 if ((*in_text_curr & 0xC0) != 0x80)
3301 return in_text_curr;
3303 return in_text_start;
3306int ImTextCountLines(
const char *in_text,
const char *in_text_end)
3308 if (in_text_end == NULL)
3309 in_text_end = in_text + ImStrlen(in_text);
3311 while (in_text < in_text_end)
3313 const char *line_end = (
const char *)ImMemchr(in_text,
'\n', in_text_end - in_text);
3314 in_text = line_end ? line_end + 1 : in_text_end;
3320IM_MSVC_RUNTIME_CHECKS_RESTORE
3327IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b)
3329 float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f;
3330 int r = ImLerp((
int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t);
3331 int g = ImLerp((
int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t);
3332 int b = ImLerp((
int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (
int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t);
3333 return IM_COL32(r, g, b, 0xFF);
3336ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
3338 float s = 1.0f / 255.0f;
3339 return ImVec4(((in >> IM_COL32_R_SHIFT) & 0xFF) * s, ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
3340 ((in >> IM_COL32_B_SHIFT) & 0xFF) * s, ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
3343ImU32 ImGui::ColorConvertFloat4ToU32(
const ImVec4 &in)
3346 out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
3347 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
3348 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
3349 out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
3355void ImGui::ColorConvertRGBtoHSV(
float r,
float g,
float b,
float &out_h,
float &out_s,
float &out_v)
3369 const float chroma = r - (g < b ? g : b);
3370 out_h = ImFabs(K + (g - b) / (6.f * chroma + 1e-20f));
3371 out_s = chroma / (r + 1e-20f);
3377void ImGui::ColorConvertHSVtoRGB(
float h,
float s,
float v,
float &out_r,
float &out_g,
float &out_b)
3382 out_r = out_g = out_b = v;
3386 h = ImFmod(h, 1.0f) / (60.0f / 360.0f);
3388 float f = h - (float)i;
3389 float p = v * (1.0f - s);
3390 float q = v * (1.0f - s * f);
3391 float t = v * (1.0f - s * (1.0f - f));
3438 for (
size_t count = (
size_t)(in_end - in_p); count > 0;)
3440 size_t count2 = count >> 1;
3445 count -= count2 + 1;
3455IM_MSVC_RUNTIME_CHECKS_OFF
3456static int IMGUI_CDECL PairComparerByID(
const void *lhs,
const void *rhs)
3462 return (lhs_v > rhs_v ? +1 : lhs_v < rhs_v ? -1 : 0);
3467void ImGuiStorage::BuildSortByKey()
3469 ImQsort(Data.Data, (
size_t)Data.Size,
sizeof(
ImGuiStoragePair), PairComparerByID);
3472int ImGuiStorage::GetInt(ImGuiID key,
int default_val)
const
3476 if (it == Data.Data + Data.Size || it->key != key)
3481bool ImGuiStorage::GetBool(ImGuiID key,
bool default_val)
const
3483 return GetInt(key, default_val ? 1 : 0) != 0;
3486float ImGuiStorage::GetFloat(ImGuiID key,
float default_val)
const
3490 if (it == Data.Data + Data.Size || it->key != key)
3495void *ImGuiStorage::GetVoidPtr(ImGuiID key)
const
3499 if (it == Data.Data + Data.Size || it->key != key)
3506int *ImGuiStorage::GetIntRef(ImGuiID key,
int default_val)
3508 ImGuiStoragePair *it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
3509 if (it == Data.Data + Data.Size || it->key != key)
3514bool *ImGuiStorage::GetBoolRef(ImGuiID key,
bool default_val)
3516 return (
bool *)GetIntRef(key, default_val ? 1 : 0);
3519float *ImGuiStorage::GetFloatRef(ImGuiID key,
float default_val)
3521 ImGuiStoragePair *it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
3522 if (it == Data.Data + Data.Size || it->key != key)
3527void **ImGuiStorage::GetVoidPtrRef(ImGuiID key,
void *default_val)
3529 ImGuiStoragePair *it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
3530 if (it == Data.Data + Data.Size || it->key != key)
3537void ImGuiStorage::SetInt(ImGuiID key,
int val)
3539 ImGuiStoragePair *it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
3540 if (it == Data.Data + Data.Size || it->key != key)
3546void ImGuiStorage::SetBool(ImGuiID key,
bool val)
3548 SetInt(key, val ? 1 : 0);
3551void ImGuiStorage::SetFloat(ImGuiID key,
float val)
3553 ImGuiStoragePair *it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
3554 if (it == Data.Data + Data.Size || it->key != key)
3560void ImGuiStorage::SetVoidPtr(ImGuiID key,
void *val)
3562 ImGuiStoragePair *it = ImLowerBound(Data.Data, Data.Data + Data.Size, key);
3563 if (it == Data.Data + Data.Size || it->key != key)
3569void ImGuiStorage::SetAllInt(
int v)
3571 for (
int i = 0; i < Data.Size; i++)
3574IM_MSVC_RUNTIME_CHECKS_RESTORE
3581ImGuiTextFilter::ImGuiTextFilter(
const char *default_filter)
3587 ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
3592bool ImGuiTextFilter::Draw(
const char *label,
float width)
3595 ImGui::SetNextItemWidth(width);
3596 bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
3599 return value_changed;
3606 const char *we = wb;
3609 if (*we == separator)
3611 out->push_back(ImGuiTextRange(wb, we));
3617 out->push_back(ImGuiTextRange(wb, we));
3620void ImGuiTextFilter::Build()
3623 ImGuiTextRange input_range(InputBuf, InputBuf + ImStrlen(InputBuf));
3624 input_range.split(
',', &Filters);
3627 for (ImGuiTextRange &f : Filters)
3629 while (f.b < f.e && ImCharIsBlankA(f.b[0]))
3631 while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
3640bool ImGuiTextFilter::PassFilter(
const char *text,
const char *text_end)
const
3642 if (Filters.Size == 0)
3646 text = text_end =
"";
3648 for (
const ImGuiTextRange &f : Filters)
3655 if (ImStristr(text, text_end, f.b + 1, f.e) != NULL)
3661 if (ImStristr(text, text_end, f.b, f.e) != NULL)
3680#if defined(__GNUC__) || defined(__clang__)
3681#define va_copy(dest, src) __builtin_va_copy(dest, src)
3683#define va_copy(dest, src) (dest = src)
3687char ImGuiTextBuffer::EmptyString[1] = {0};
3689void ImGuiTextBuffer::append(
const char *str,
const char *str_end)
3691 int len = str_end ? (int)(str_end - str) : (int)ImStrlen(str);
3694 const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
3695 const int needed_sz = write_off + len;
3696 if (write_off + len >= Buf.Capacity)
3698 int new_capacity = Buf.Capacity * 2;
3699 Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
3702 Buf.resize(needed_sz);
3703 memcpy(&Buf[write_off - 1], str, (
size_t)len);
3704 Buf[write_off - 1 + len] = 0;
3707void ImGuiTextBuffer::appendf(
const char *fmt, ...)
3710 va_start(args, fmt);
3711 appendfv(fmt, args);
3716void ImGuiTextBuffer::appendfv(
const char *fmt, va_list args)
3719 va_copy(args_copy, args);
3721 int len = ImFormatStringV(NULL, 0, fmt,
3730 const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
3731 const int needed_sz = write_off + len;
3732 if (write_off + len >= Buf.Capacity)
3734 int new_capacity = Buf.Capacity * 2;
3735 Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
3738 Buf.resize(needed_sz);
3739 ImFormatStringV(&Buf[write_off - 1], (
size_t)len + 1, fmt, args_copy);
3743void ImGuiTextIndex::append(
const char *base,
int old_size,
int new_size)
3745 IM_ASSERT(old_size >= 0 && new_size >= old_size && new_size >= EndOffset);
3746 if (old_size == new_size)
3748 if (EndOffset == 0 || base[EndOffset - 1] ==
'\n')
3749 LineOffsets.push_back(EndOffset);
3750 const char *base_end = base + new_size;
3751 for (
const char *p = base + old_size; (p = (
const char *)ImMemchr(p,
'\n', base_end - p)) != 0;)
3753 LineOffsets.push_back((
int)(intptr_t)(p - base));
3754 EndOffset = ImMax(EndOffset, new_size);
3763static bool GetSkipItemForListClipping()
3766 return (g.CurrentTable ? g.CurrentTable->HostSkipItems : g.CurrentWindow->SkipItems);
3771 if (ranges.Size - offset <= 1)
3776 for (
int sort_end = ranges.Size - offset - 1; sort_end > 0; --sort_end)
3777 for (
int i = offset; i < sort_end + offset; ++i)
3778 if (ranges[i].Min > ranges[i + 1].Min)
3779 ImSwap(ranges[i], ranges[i + 1]);
3782 for (
int i = 1 + offset; i < ranges.Size; i++)
3784 IM_ASSERT(!ranges[i].PosToIndexConvert && !ranges[i - 1].PosToIndexConvert);
3785 if (ranges[i - 1].Max < ranges[i].Min)
3787 ranges[i - 1].Min = ImMin(ranges[i - 1].Min, ranges[i].Min);
3788 ranges[i - 1].Max = ImMax(ranges[i - 1].Max, ranges[i].Max);
3789 ranges.erase(ranges.Data + i);
3794static void ImGuiListClipper_SeekCursorAndSetupPrevLine(
float pos_y,
float line_height)
3802 float off_y = pos_y - window->DC.CursorPos.y;
3803 window->DC.CursorPos.y = pos_y;
3804 window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y - g.Style.ItemSpacing.y);
3805 window->DC.CursorPosPrevLine.y =
3806 window->DC.CursorPos.y - line_height;
3808 window->DC.PrevLineSize.y =
3814 columns->LineMinY = window->DC.CursorPos.y;
3817 if (table->IsInsideRow)
3818 ImGui::TableEndRow(table);
3819 table->RowPosY2 = window->DC.CursorPos.y;
3820 const int row_increase = (int)((off_y / line_height) + 0.5f);
3822 table->RowBgColorCounter += row_increase;
3826ImGuiListClipper::ImGuiListClipper()
3828 memset(
this, 0,
sizeof(*
this));
3831ImGuiListClipper::~ImGuiListClipper()
3836void ImGuiListClipper::Begin(
int items_count,
float items_height)
3839 Ctx = ImGui::GetCurrentContext();
3843 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Begin(%d,%.2f) in '%s'\n", items_count, items_height, window->Name);
3846 if (table->IsInsideRow)
3847 ImGui::TableEndRow(table);
3849 StartPosY = window->DC.CursorPos.y;
3850 ItemsHeight = items_height;
3851 ItemsCount = items_count;
3856 if (++g.ClipperTempDataStacked > g.ClipperTempData.Size)
3860 data->LossynessOffset = window->DC.CursorStartPosLossyness.y;
3862 StartSeekOffsetY = data->LossynessOffset;
3865void ImGuiListClipper::End()
3872 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: End() in '%s'\n", g.CurrentWindow->Name);
3873 if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0)
3874 SeekCursorForItem(ItemsCount);
3877 IM_ASSERT(data->ListClipper ==
this);
3878 data->StepNo = data->Ranges.Size;
3879 if (--g.ClipperTempDataStacked > 0)
3881 data = &g.ClipperTempData[g.ClipperTempDataStacked - 1];
3882 data->ListClipper->TempData = data;
3889void ImGuiListClipper::IncludeItemsByIndex(
int item_begin,
int item_end)
3892 IM_ASSERT(DisplayStart < 0);
3893 IM_ASSERT(item_begin <= item_end);
3894 if (item_begin < item_end)
3895 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(item_begin, item_end));
3901void ImGuiListClipper::SeekCursorForItem(
int item_n)
3908 float pos_y = (float)((
double)StartPosY + StartSeekOffsetY + (double)item_n * ItemsHeight);
3909 ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, ItemsHeight);
3917 IM_ASSERT(data != NULL &&
"Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?");
3920 if (table && table->IsInsideRow)
3921 ImGui::TableEndRow(table);
3924 if (clipper->ItemsCount == 0 || GetSkipItemForListClipping())
3929 if (data->StepNo == 0 && table != NULL && !table->IsUnfrozenRows)
3931 clipper->DisplayStart = data->ItemsFrozen;
3932 clipper->DisplayEnd = ImMin(data->ItemsFrozen + 1, clipper->ItemsCount);
3933 if (clipper->DisplayStart < clipper->DisplayEnd)
3934 data->ItemsFrozen++;
3940 bool calc_clipping =
false;
3941 if (data->StepNo == 0)
3943 clipper->StartPosY = window->DC.CursorPos.y;
3944 if (clipper->ItemsHeight <= 0.0f)
3947 data->Ranges.push_front(ImGuiListClipperRange::FromIndices(data->ItemsFrozen, data->ItemsFrozen + 1));
3948 clipper->DisplayStart = ImMax(data->Ranges[0].Min, data->ItemsFrozen);
3949 clipper->DisplayEnd = ImMin(data->Ranges[0].Max, clipper->ItemsCount);
3953 calc_clipping =
true;
3957 if (clipper->ItemsHeight <= 0.0f)
3959 IM_ASSERT(data->StepNo == 1);
3961 IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y);
3963 clipper->ItemsHeight =
3964 (window->DC.CursorPos.y - clipper->StartPosY) / (
float)(clipper->DisplayEnd - clipper->DisplayStart);
3965 bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) ||
3966 ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y);
3967 if (affected_by_floating_point_precision)
3968 clipper->ItemsHeight = window->DC.PrevLineSize.y +
3969 g.Style.ItemSpacing.y;
3970 if (clipper->ItemsHeight == 0.0f &&
3971 clipper->ItemsCount == INT_MAX)
3973 IM_ASSERT(clipper->ItemsHeight > 0.0f &&
3974 "Unable to calculate item height! First item hasn't moved the cursor vertically!");
3975 calc_clipping =
true;
3979 const int already_submitted = clipper->DisplayEnd;
3983 clipper->StartSeekOffsetY = (double)data->LossynessOffset - data->ItemsFrozen * (
double)clipper->ItemsHeight;
3988 data->Ranges.push_back(ImGuiListClipperRange::FromIndices(0, clipper->ItemsCount));
3993 const bool is_nav_request =
3994 (g.NavMoveScoringItems && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav);
3996 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(g.NavScoringNoClipRect.Min.y,
3997 g.NavScoringNoClipRect.Max.y, 0, 0));
3998 if (is_nav_request && (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && g.NavTabbingDir == -1)
3999 data->Ranges.push_back(
4000 ImGuiListClipperRange::FromIndices(clipper->ItemsCount - 1, clipper->ItemsCount));
4003 ImRect nav_rect_abs = ImGui::WindowRectRelToAbs(window, window->NavRectRel[0]);
4004 if (g.NavId != 0 && window->NavLastIds[0] == g.NavId)
4005 data->Ranges.push_back(
4006 ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0));
4009 float min_y = window->ClipRect.Min.y;
4010 float max_y = window->ClipRect.Max.y;
4014 if (bs->IsActive && bs->Window == window)
4020 min_y -= g.Style.ItemSpacing.y;
4021 max_y += g.Style.ItemSpacing.y;
4025 data->Ranges.push_back(
4026 ImGuiListClipperRange::FromPositions(bs->UnclipRect.Min.y, bs->UnclipRect.Max.y, 0, 0));
4029 const int off_min = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0;
4030 const int off_max = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0;
4031 data->Ranges.push_back(ImGuiListClipperRange::FromPositions(min_y, max_y, off_min, off_max));
4040 if (range.PosToIndexConvert)
4043 (int)(((
double)range.Min - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight);
4044 int m2 = (int)((((
double)range.Max - window->DC.CursorPos.y - data->LossynessOffset) /
4045 clipper->ItemsHeight) +
4047 range.Min = ImClamp(already_submitted + m1 + range.PosToIndexOffsetMin, already_submitted,
4048 clipper->ItemsCount - 1);
4050 ImClamp(already_submitted + m2 + range.PosToIndexOffsetMax, range.Min + 1, clipper->ItemsCount);
4051 range.PosToIndexConvert =
false;
4053 ImGuiListClipper_SortAndFuseRanges(data->Ranges, data->StepNo);
4057 while (data->StepNo < data->Ranges.Size)
4059 clipper->DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted);
4060 clipper->DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, clipper->ItemsCount);
4062 if (clipper->DisplayStart >= clipper->DisplayEnd)
4064 if (clipper->DisplayStart > already_submitted)
4065 clipper->SeekCursorForItem(clipper->DisplayStart);
4071 if (clipper->ItemsCount < INT_MAX)
4072 clipper->SeekCursorForItem(clipper->ItemsCount);
4077bool ImGuiListClipper::Step()
4080 bool need_items_height = (ItemsHeight <= 0.0f);
4081 bool ret = ImGuiListClipper_StepInternal(
this);
4082 if (ret && (DisplayStart >= DisplayEnd))
4084 if (g.CurrentTable && g.CurrentTable->IsUnfrozenRows ==
false)
4085 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): inside frozen table row.\n");
4086 if (need_items_height && ItemsHeight > 0.0f)
4087 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): computed ItemsHeight: %.2f.\n", ItemsHeight);
4090 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): display %d to %d.\n", DisplayStart, DisplayEnd);
4094 IMGUI_DEBUG_LOG_CLIPPER(
"Clipper: Step(): End.\n");
4106 IM_ASSERT(GImGui != NULL &&
4107 "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
4108 return GImGui->Style;
4111ImU32 ImGui::GetColorU32(ImGuiCol idx,
float alpha_mul)
4114 ImVec4 c = style.Colors[idx];
4115 c.w *= style.Alpha * alpha_mul;
4116 return ColorConvertFloat4ToU32(c);
4119ImU32 ImGui::GetColorU32(
const ImVec4 &col)
4124 return ColorConvertFloat4ToU32(c);
4127const ImVec4 &ImGui::GetStyleColorVec4(ImGuiCol idx)
4130 return style.Colors[idx];
4133ImU32 ImGui::GetColorU32(ImU32 col,
float alpha_mul)
4136 alpha_mul *= style.Alpha;
4137 if (alpha_mul >= 1.0f)
4139 ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
4140 a = (ImU32)(a * alpha_mul);
4141 return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
4146void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)
4151 backup.BackupValue = g.Style.Colors[idx];
4152 g.ColorStack.push_back(backup);
4153 if (g.DebugFlashStyleColorIdx != idx)
4154 g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
4157void ImGui::PushStyleColor(ImGuiCol idx,
const ImVec4 &col)
4162 backup.BackupValue = g.Style.Colors[idx];
4163 g.ColorStack.push_back(backup);
4164 if (g.DebugFlashStyleColorIdx != idx)
4165 g.Style.Colors[idx] = col;
4168void ImGui::PopStyleColor(
int count)
4171 if (g.ColorStack.Size < count)
4173 IM_ASSERT_USER_ERROR(0,
"Calling PopStyleColor() too many times!");
4174 count = g.ColorStack.Size;
4179 g.Style.Colors[backup.Col] = backup.BackupValue;
4180 g.ColorStack.pop_back();
4185static const ImGuiCol GWindowDockStyleColors[ImGuiWindowDockStyleCol_COUNT] = {
4187 ImGuiCol_TabHovered,
4189 ImGuiCol_TabSelected,
4190 ImGuiCol_TabSelectedOverline,
4192 ImGuiCol_TabDimmedSelected,
4193 ImGuiCol_TabDimmedSelectedOverline,
4197 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, Alpha)},
4198 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, DisabledAlpha)},
4199 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, WindowPadding)},
4200 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, WindowRounding)},
4201 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, WindowBorderSize)},
4202 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, WindowMinSize)},
4203 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, WindowTitleAlign)},
4204 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, ChildRounding)},
4205 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, ChildBorderSize)},
4206 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, PopupRounding)},
4207 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, PopupBorderSize)},
4208 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, FramePadding)},
4209 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, FrameRounding)},
4210 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, FrameBorderSize)},
4211 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, ItemSpacing)},
4212 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, ItemInnerSpacing)},
4213 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, IndentSpacing)},
4214 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, CellPadding)},
4215 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, ScrollbarSize)},
4216 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, ScrollbarRounding)},
4217 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, GrabMinSize)},
4218 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, GrabRounding)},
4219 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, ImageBorderSize)},
4220 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, TabRounding)},
4221 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, TabBorderSize)},
4222 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, TabBarBorderSize)},
4223 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, TabBarOverlineSize)},
4224 {1, ImGuiDataType_Float,
4225 (ImU32)offsetof(
ImGuiStyle, TableAngledHeadersAngle)},
4226 {2, ImGuiDataType_Float,
4227 (ImU32)offsetof(
ImGuiStyle, TableAngledHeadersTextAlign)},
4228 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, ButtonTextAlign)},
4229 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, SelectableTextAlign)},
4230 {1, ImGuiDataType_Float,
4231 (ImU32)offsetof(
ImGuiStyle, SeparatorTextBorderSize)},
4232 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, SeparatorTextAlign)},
4233 {2, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, SeparatorTextPadding)},
4234 {1, ImGuiDataType_Float, (ImU32)offsetof(
ImGuiStyle, DockingSeparatorSize)},
4239 IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
4240 IM_STATIC_ASSERT(IM_ARRAYSIZE(GStyleVarsInfo) == ImGuiStyleVar_COUNT);
4241 return &GStyleVarsInfo[idx];
4244void ImGui::PushStyleVar(ImGuiStyleVar idx,
float val)
4248 if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 1)
4250 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
4253 float *pvar = (
float *)var_info->GetVarPtr(&g.Style);
4258void ImGui::PushStyleVarX(ImGuiStyleVar idx,
float val_x)
4262 if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2)
4264 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
4267 ImVec2 *pvar = (
ImVec2 *)var_info->GetVarPtr(&g.Style);
4272void ImGui::PushStyleVarY(ImGuiStyleVar idx,
float val_y)
4276 if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2)
4278 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
4281 ImVec2 *pvar = (
ImVec2 *)var_info->GetVarPtr(&g.Style);
4286void ImGui::PushStyleVar(ImGuiStyleVar idx,
const ImVec2 &val)
4290 if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2)
4292 IM_ASSERT_USER_ERROR(0,
"Calling PushStyleVar() variant with wrong type!");
4295 ImVec2 *pvar = (
ImVec2 *)var_info->GetVarPtr(&g.Style);
4300void ImGui::PopStyleVar(
int count)
4303 if (g.StyleVarStack.Size < count)
4305 IM_ASSERT_USER_ERROR(0,
"Calling PopStyleVar() too many times!");
4306 count = g.StyleVarStack.Size;
4314 void *data = var_info->GetVarPtr(&g.Style);
4315 if (var_info->DataType == ImGuiDataType_Float && var_info->Count == 1)
4317 ((
float *)data)[0] = backup.BackupFloat[0];
4319 else if (var_info->DataType == ImGuiDataType_Float && var_info->Count == 2)
4321 ((
float *)data)[0] = backup.BackupFloat[0];
4322 ((
float *)data)[1] = backup.BackupFloat[1];
4324 g.StyleVarStack.pop_back();
4329const char *ImGui::GetStyleColorName(ImGuiCol idx)
4336 case ImGuiCol_TextDisabled:
4337 return "TextDisabled";
4338 case ImGuiCol_WindowBg:
4340 case ImGuiCol_ChildBg:
4342 case ImGuiCol_PopupBg:
4344 case ImGuiCol_Border:
4346 case ImGuiCol_BorderShadow:
4347 return "BorderShadow";
4348 case ImGuiCol_FrameBg:
4350 case ImGuiCol_FrameBgHovered:
4351 return "FrameBgHovered";
4352 case ImGuiCol_FrameBgActive:
4353 return "FrameBgActive";
4354 case ImGuiCol_TitleBg:
4356 case ImGuiCol_TitleBgActive:
4357 return "TitleBgActive";
4358 case ImGuiCol_TitleBgCollapsed:
4359 return "TitleBgCollapsed";
4360 case ImGuiCol_MenuBarBg:
4362 case ImGuiCol_ScrollbarBg:
4363 return "ScrollbarBg";
4364 case ImGuiCol_ScrollbarGrab:
4365 return "ScrollbarGrab";
4366 case ImGuiCol_ScrollbarGrabHovered:
4367 return "ScrollbarGrabHovered";
4368 case ImGuiCol_ScrollbarGrabActive:
4369 return "ScrollbarGrabActive";
4370 case ImGuiCol_CheckMark:
4372 case ImGuiCol_SliderGrab:
4373 return "SliderGrab";
4374 case ImGuiCol_SliderGrabActive:
4375 return "SliderGrabActive";
4376 case ImGuiCol_Button:
4378 case ImGuiCol_ButtonHovered:
4379 return "ButtonHovered";
4380 case ImGuiCol_ButtonActive:
4381 return "ButtonActive";
4382 case ImGuiCol_Header:
4384 case ImGuiCol_HeaderHovered:
4385 return "HeaderHovered";
4386 case ImGuiCol_HeaderActive:
4387 return "HeaderActive";
4388 case ImGuiCol_Separator:
4390 case ImGuiCol_SeparatorHovered:
4391 return "SeparatorHovered";
4392 case ImGuiCol_SeparatorActive:
4393 return "SeparatorActive";
4394 case ImGuiCol_ResizeGrip:
4395 return "ResizeGrip";
4396 case ImGuiCol_ResizeGripHovered:
4397 return "ResizeGripHovered";
4398 case ImGuiCol_ResizeGripActive:
4399 return "ResizeGripActive";
4400 case ImGuiCol_InputTextCursor:
4401 return "InputTextCursor";
4402 case ImGuiCol_TabHovered:
4403 return "TabHovered";
4406 case ImGuiCol_TabSelected:
4407 return "TabSelected";
4408 case ImGuiCol_TabSelectedOverline:
4409 return "TabSelectedOverline";
4410 case ImGuiCol_TabDimmed:
4412 case ImGuiCol_TabDimmedSelected:
4413 return "TabDimmedSelected";
4414 case ImGuiCol_TabDimmedSelectedOverline:
4415 return "TabDimmedSelectedOverline";
4416 case ImGuiCol_DockingPreview:
4417 return "DockingPreview";
4418 case ImGuiCol_DockingEmptyBg:
4419 return "DockingEmptyBg";
4420 case ImGuiCol_PlotLines:
4422 case ImGuiCol_PlotLinesHovered:
4423 return "PlotLinesHovered";
4424 case ImGuiCol_PlotHistogram:
4425 return "PlotHistogram";
4426 case ImGuiCol_PlotHistogramHovered:
4427 return "PlotHistogramHovered";
4428 case ImGuiCol_TableHeaderBg:
4429 return "TableHeaderBg";
4430 case ImGuiCol_TableBorderStrong:
4431 return "TableBorderStrong";
4432 case ImGuiCol_TableBorderLight:
4433 return "TableBorderLight";
4434 case ImGuiCol_TableRowBg:
4435 return "TableRowBg";
4436 case ImGuiCol_TableRowBgAlt:
4437 return "TableRowBgAlt";
4438 case ImGuiCol_TextLink:
4440 case ImGuiCol_TextSelectedBg:
4441 return "TextSelectedBg";
4442 case ImGuiCol_DragDropTarget:
4443 return "DragDropTarget";
4444 case ImGuiCol_NavCursor:
4446 case ImGuiCol_NavWindowingHighlight:
4447 return "NavWindowingHighlight";
4448 case ImGuiCol_NavWindowingDimBg:
4449 return "NavWindowingDimBg";
4450 case ImGuiCol_ModalWindowDimBg:
4451 return "ModalWindowDimBg";
4464const char *ImGui::FindRenderedTextEnd(
const char *text,
const char *text_end)
4466 const char *text_display_end = text;
4468 text_end = (
const char *)-1;
4470 while (text_display_end < text_end && *text_display_end !=
'\0' &&
4471 (text_display_end[0] !=
'#' || text_display_end[1] !=
'#'))
4473 return text_display_end;
4478void ImGui::RenderText(
ImVec2 pos,
const char *text,
const char *text_end,
bool hide_text_after_hash)
4484 const char *text_display_end;
4485 if (hide_text_after_hash)
4487 text_display_end = FindRenderedTextEnd(text, text_end);
4492 text_end = text + ImStrlen(text);
4493 text_display_end = text_end;
4496 if (text != text_display_end)
4498 window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
4500 LogRenderedText(&pos, text, text_display_end);
4504void ImGui::RenderTextWrapped(
ImVec2 pos,
const char *text,
const char *text_end,
float wrap_width)
4510 text_end = text + ImStrlen(text);
4512 if (text != text_end)
4514 window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
4516 LogRenderedText(&pos, text, text_end);
4527void ImGui::RenderTextClippedEx(
ImDrawList *draw_list,
const ImVec2 &pos_min,
const ImVec2 &pos_max,
const char *text,
4528 const char *text_display_end,
const ImVec2 *text_size_if_known,
const ImVec2 &align,
4534 text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end,
false, 0.0f);
4536 const ImVec2 *clip_min = clip_rect ? &clip_rect->Min : &pos_min;
4537 const ImVec2 *clip_max = clip_rect ? &clip_rect->Max : &pos_max;
4538 bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
4540 need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);
4545 pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
4547 pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);
4552 ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
4553 draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
4557 draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
4561void ImGui::RenderTextClipped(
const ImVec2 &pos_min,
const ImVec2 &pos_max,
const char *text,
const char *text_end,
4565 const char *text_display_end = FindRenderedTextEnd(text, text_end);
4566 const int text_len = (int)(text_display_end - text);
4572 RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align,
4575 LogRenderedText(&pos_min, text, text_display_end);
4582void ImGui::RenderTextEllipsis(
ImDrawList *draw_list,
const ImVec2 &pos_min,
const ImVec2 &pos_max,
float clip_max_x,
4583 float ellipsis_max_x,
const char *text,
const char *text_end_full,
4584 const ImVec2 *text_size_if_known)
4587 if (text_end_full == NULL)
4588 text_end_full = FindRenderedTextEnd(text);
4589 const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full,
false, 0.0f);
4597 if (text_size.x > pos_max.x - pos_min.x)
4604 ImFont *font = draw_list->_Data->Font;
4605 const float font_size = draw_list->_Data->FontSize;
4606 const float font_scale = draw_list->_Data->FontScale;
4607 const char *text_end_ellipsis = NULL;
4608 const float ellipsis_width = font->EllipsisWidth * font_scale;
4611 const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_width) - pos_min.x, 1.0f);
4612 float text_size_clipped_x =
4613 font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
4614 if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
4617 text_end_ellipsis = text + ImTextCountUtf8BytesFromChar(text, text_end_full);
4618 text_size_clipped_x = font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text, text_end_ellipsis).x;
4620 while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1]))
4624 text_end_ellipsis--;
4625 text_size_clipped_x -=
4626 font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1)
4631 RenderTextClippedEx(draw_list, pos_min,
ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size,
4633 ImVec2 ellipsis_pos = ImTrunc(
ImVec2(pos_min.x + text_size_clipped_x, pos_min.y));
4634 if (ellipsis_pos.x + ellipsis_width <= ellipsis_max_x)
4635 for (
int i = 0; i < font->EllipsisCharCount; i++, ellipsis_pos.x += font->EllipsisCharStep * font_scale)
4636 font->RenderChar(draw_list, font_size, ellipsis_pos, GetColorU32(ImGuiCol_Text), font->EllipsisChar);
4640 RenderTextClippedEx(draw_list, pos_min,
ImVec2(clip_max_x, pos_max.y), text, text_end_full, &text_size,
4645 LogRenderedText(&pos_min, text, text_end_full);
4649void ImGui::RenderFrame(
ImVec2 p_min,
ImVec2 p_max, ImU32 fill_col,
bool borders,
float rounding)
4653 window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
4654 const float border_size = g.Style.FrameBorderSize;
4655 if (borders && border_size > 0.0f)
4657 window->DrawList->AddRect(p_min +
ImVec2(1, 1), p_max +
ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow),
4658 rounding, 0, border_size);
4659 window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
4663void ImGui::RenderFrameBorder(
ImVec2 p_min,
ImVec2 p_max,
float rounding)
4667 const float border_size = g.Style.FrameBorderSize;
4668 if (border_size > 0.0f)
4670 window->DrawList->AddRect(p_min +
ImVec2(1, 1), p_max +
ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow),
4671 rounding, 0, border_size);
4672 window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
4676void ImGui::RenderNavCursor(
const ImRect &bb, ImGuiID
id, ImGuiNavRenderCursorFlags flags)
4681 if (!g.NavCursorVisible && !(flags & ImGuiNavRenderCursorFlags_AlwaysDraw))
4683 if (
id == g.LastItemData.ID && (g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav))
4686 if (window->DC.NavHideHighlightOneFrame)
4689 float rounding = (flags & ImGuiNavRenderCursorFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
4690 ImRect display_rect = bb;
4691 display_rect.ClipWith(window->ClipRect);
4692 const float thickness = 2.0f;
4693 if (flags & ImGuiNavRenderCursorFlags_Compact)
4695 window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0,
4700 const float distance = 3.0f + thickness * 0.5f;
4701 display_rect.Expand(
ImVec2(distance, distance));
4702 bool fully_visible = window->ClipRect.Contains(display_rect);
4704 window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
4705 window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0,
4708 window->DrawList->PopClipRect();
4712void ImGui::RenderMouseCursor(
ImVec2 base_pos,
float base_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill,
4713 ImU32 col_border, ImU32 col_shadow)
4716 if (mouse_cursor <= ImGuiMouseCursor_None ||
4717 mouse_cursor >= ImGuiMouseCursor_COUNT)
4718 mouse_cursor = ImGuiMouseCursor_Arrow;
4719 ImFontAtlas *font_atlas = g.DrawListSharedData.Font->ContainerAtlas;
4724 ImVec2 offset, size, uv[4];
4725 if (!ImFontAtlasGetMouseCursorTexData(font_atlas, mouse_cursor, &offset, &size, &uv[0], &uv[2]))
4727 const ImVec2 pos = base_pos - offset;
4728 const float scale = base_scale * viewport->DpiScale;
4729 if (!viewport->GetMainRect().Overlaps(
ImRect(pos, pos +
ImVec2(size.x + 2, size.y + 2) * scale)))
4731 ImDrawList *draw_list = GetForegroundDrawList(viewport);
4732 ImTextureID tex_id = font_atlas->TexID;
4733 draw_list->PushTextureID(tex_id);
4734 draw_list->AddImage(tex_id, pos +
ImVec2(1, 0) * scale, pos + (
ImVec2(1, 0) + size) * scale, uv[2], uv[3],
4736 draw_list->AddImage(tex_id, pos +
ImVec2(2, 0) * scale, pos + (
ImVec2(2, 0) + size) * scale, uv[2], uv[3],
4738 draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border);
4739 draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill);
4740 if (mouse_cursor == ImGuiMouseCursor_Wait || mouse_cursor == ImGuiMouseCursor_Progress)
4742 float a_min = ImFmod((
float)g.Time * 5.0f, 2.0f * IM_PI);
4743 float a_max = a_min + IM_PI * 1.65f;
4744 draw_list->PathArcTo(pos +
ImVec2(14, -1) * scale, 6.0f * scale, a_min, a_max);
4745 draw_list->PathStroke(col_fill, ImDrawFlags_None, 3.0f * scale);
4747 draw_list->PopTextureID();
4765#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
4766 IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx);
4772void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func,
void *user_data)
4774 GImAllocatorAllocFunc = alloc_func;
4775 GImAllocatorFreeFunc = free_func;
4776 GImAllocatorUserData = user_data;
4781void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc *p_alloc_func, ImGuiMemFreeFunc *p_free_func,
void **p_user_data)
4783 *p_alloc_func = GImAllocatorAllocFunc;
4784 *p_free_func = GImAllocatorFreeFunc;
4785 *p_user_data = GImAllocatorUserData;
4792 SetCurrentContext(ctx);
4794 if (prev_ctx != NULL)
4795 SetCurrentContext(prev_ctx);
4804 SetCurrentContext(ctx);
4806 SetCurrentContext((prev_ctx != ctx) ? prev_ctx : NULL);
4813 {ImGuiLocKey_VersionStr,
"Dear ImGui " IMGUI_VERSION
" (" IM_STRINGIFY(IMGUI_VERSION_NUM)
")"},
4814 {ImGuiLocKey_TableSizeOne,
"Size column to fit###SizeOne"},
4815 {ImGuiLocKey_TableSizeAllFit,
"Size all columns to fit###SizeAll"},
4816 {ImGuiLocKey_TableSizeAllDefault,
"Size all columns to default###SizeAll"},
4817 {ImGuiLocKey_TableResetOrder,
"Reset order###ResetOrder"},
4818 {ImGuiLocKey_WindowingMainMenuBar,
"(Main menu bar)"},
4819 {ImGuiLocKey_WindowingPopup,
"(Popup)"},
4820 {ImGuiLocKey_WindowingUntitled,
"(Untitled)"},
4821 {ImGuiLocKey_OpenLink_s,
"Open '%s'"},
4822 {ImGuiLocKey_CopyLink,
"Copy Link###CopyLink"},
4823 {ImGuiLocKey_DockingHideTabBar,
"Hide tab bar###HideTabBar"},
4824 {ImGuiLocKey_DockingHoldShiftToDock,
"Hold SHIFT to enable Docking window."},
4825 {ImGuiLocKey_DockingDragToUndockOrMoveNode,
"Click and drag to move or undock whole node."},
4828ImGuiContext::ImGuiContext(
ImFontAtlas *shared_font_atlas)
4831 InputTextState.Ctx =
this;
4833 Initialized =
false;
4834 ConfigFlagsCurrFrame = ConfigFlagsLastFrame = ImGuiConfigFlags_None;
4835 FontAtlasOwnedByContext = shared_font_atlas ? false :
true;
4837 FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f;
4838 IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(
ImFontAtlas)();
4841 FrameCountEnded = FrameCountPlatformEnded = FrameCountRendered = -1;
4842 WithinEndChildID = 0;
4843 WithinFrameScope = WithinFrameScopeWithImplicitWindow =
false;
4844 GcCompactAll =
false;
4845 TestEngineHookItems =
false;
4847 memset(ContextName, 0,
sizeof(ContextName));
4849 InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
4850 InputEventsNextEventId = 1;
4852 WindowsActiveCount = 0;
4853 WindowsBorderHoverPadding = 0.0f;
4854 CurrentWindow = NULL;
4855 HoveredWindow = NULL;
4856 HoveredWindowUnderMovingWindow = NULL;
4857 HoveredWindowBeforeClear = NULL;
4858 MovingWindow = NULL;
4859 WheelingWindow = NULL;
4860 WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1;
4861 WheelingWindowReleaseTimer = 0.0f;
4863 DebugDrawIdConflicts = 0;
4864 DebugHookIdInfo = 0;
4865 HoveredId = HoveredIdPreviousFrame = 0;
4866 HoveredIdPreviousFrameItemCount = 0;
4867 HoveredIdAllowOverlap =
false;
4868 HoveredIdIsDisabled =
false;
4869 HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
4870 ItemUnclipByLog =
false;
4872 ActiveIdIsAlive = 0;
4873 ActiveIdTimer = 0.0f;
4874 ActiveIdIsJustActivated =
false;
4875 ActiveIdAllowOverlap =
false;
4876 ActiveIdNoClearOnFocusLoss =
false;
4877 ActiveIdHasBeenPressedBefore =
false;
4878 ActiveIdHasBeenEditedBefore =
false;
4879 ActiveIdHasBeenEditedThisFrame =
false;
4880 ActiveIdFromShortcut =
false;
4881 ActiveIdClickOffset =
ImVec2(-1, -1);
4882 ActiveIdWindow = NULL;
4883 ActiveIdSource = ImGuiInputSource_None;
4884 ActiveIdMouseButton = -1;
4885 ActiveIdPreviousFrame = 0;
4886 memset(&DeactivatedItemData, 0,
sizeof(DeactivatedItemData));
4887 memset(&ActiveIdValueOnActivation, 0,
sizeof(ActiveIdValueOnActivation));
4889 LastActiveIdTimer = 0.0f;
4891 LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0;
4893 ActiveIdUsingNavDirMask = 0x00;
4894 ActiveIdUsingAllKeyboardKeys =
false;
4896 CurrentFocusScopeId = 0;
4897 CurrentItemFlags = ImGuiItemFlags_None;
4898 DebugShowGroupRects =
false;
4900 CurrentViewport = NULL;
4901 MouseViewport = MouseLastHoveredViewport = NULL;
4902 PlatformLastFocusedViewportId = 0;
4903 ViewportCreatedCount = PlatformWindowsCreatedCount = 0;
4904 ViewportFocusedStampCount = 0;
4906 NavCursorVisible =
false;
4907 NavHighlightItemUnderNav =
false;
4908 NavMousePosDirty =
false;
4909 NavIdIsAlive =
false;
4912 NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
4913 NavLayer = ImGuiNavLayer_Main;
4914 NavNextActivateId = 0;
4915 NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
4916 NavHighlightActivatedId = 0;
4917 NavHighlightActivatedTimer = 0.0f;
4918 NavInputSource = ImGuiInputSource_Keyboard;
4919 NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
4920 NavCursorHideFrames = 0;
4922 NavAnyRequest =
false;
4923 NavInitRequest =
false;
4924 NavInitRequestFromMove =
false;
4925 NavMoveSubmitted =
false;
4926 NavMoveScoringItems =
false;
4927 NavMoveForwardToNextFrame =
false;
4928 NavMoveFlags = ImGuiNavMoveFlags_None;
4929 NavMoveScrollFlags = ImGuiScrollFlags_None;
4930 NavMoveKeyMods = ImGuiMod_None;
4931 NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
4932 NavScoringDebugCount = 0;
4934 NavTabbingCounter = 0;
4936 NavJustMovedFromFocusScopeId = NavJustMovedToId = NavJustMovedToFocusScopeId = 0;
4937 NavJustMovedToKeyMods = ImGuiMod_None;
4938 NavJustMovedToIsTabbing =
false;
4939 NavJustMovedToHasSelectionData =
false;
4944 ConfigNavWindowingWithGamepad =
true;
4945 ConfigNavWindowingKeyNext =
4946 IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiKey_Tab);
4947 ConfigNavWindowingKeyPrev = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab)
4948 : (ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab);
4949 NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
4950 NavWindowingInputSource = ImGuiInputSource_None;
4951 NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
4952 NavWindowingToggleLayer =
false;
4953 NavWindowingToggleKey = ImGuiKey_None;
4957 DragDropActive = DragDropWithinSource = DragDropWithinTarget =
false;
4958 DragDropSourceFlags = ImGuiDragDropFlags_None;
4959 DragDropSourceFrameCount = -1;
4960 DragDropMouseButton = -1;
4961 DragDropTargetId = 0;
4962 DragDropAcceptFlags = ImGuiDragDropFlags_None;
4963 DragDropAcceptIdCurrRectSurface = 0.0f;
4964 DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0;
4965 DragDropAcceptFrameCount = -1;
4966 DragDropHoldJustPressedId = 0;
4967 memset(DragDropPayloadBufLocal, 0,
sizeof(DragDropPayloadBufLocal));
4969 ClipperTempDataStacked = 0;
4971 CurrentTable = NULL;
4972 TablesTempDataStacked = 0;
4973 CurrentTabBar = NULL;
4974 CurrentMultiSelect = NULL;
4975 MultiSelectTempDataStacked = 0;
4977 HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId =
4979 HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
4981 MouseCursor = ImGuiMouseCursor_Arrow;
4982 MouseStationaryTimer = 0.0f;
4985 memset(&DataTypeZeroValue, 0,
sizeof(DataTypeZeroValue));
4986 BeginMenuDepth = BeginComboDepth = 0;
4987 ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
4988 ColorEditCurrentID = ColorEditSavedID = 0;
4989 ColorEditSavedHue = ColorEditSavedSat = 0.0f;
4990 ColorEditSavedColor = 0;
4991 WindowResizeRelativeMode =
false;
4992 ScrollbarSeekMode = 0;
4993 ScrollbarClickDeltaToGrabCenter = 0.0f;
4994 SliderGrabClickOffset = 0.0f;
4995 SliderCurrentAccum = 0.0f;
4996 SliderCurrentAccumDirty =
false;
4997 DragCurrentAccumDirty =
false;
4998 DragCurrentAccum = 0.0f;
4999 DragSpeedDefaultRatio = 1.0f / 100.0f;
5000 DisabledAlphaBackup = 0.0f;
5001 DisabledStackSize = 0;
5002 TooltipOverrideCount = 0;
5003 TooltipPreviousWindow = NULL;
5005 PlatformImeData.InputPos =
ImVec2(0.0f, 0.0f);
5006 PlatformImeDataPrev.InputPos =
ImVec2(-1.0f, -1.0f);
5007 PlatformImeViewport = 0;
5009 DockNodeWindowMenuHandler = NULL;
5011 SettingsLoaded =
false;
5012 SettingsDirtyTimer = 0.0f;
5015 memset(LocalizationTable, 0,
sizeof(LocalizationTable));
5018 LogFlags = ImGuiLogFlags_None;
5020 LogNextPrefix = LogNextSuffix = NULL;
5022 LogLinePosY = FLT_MAX;
5023 LogLineFirstItem =
false;
5025 LogDepthToExpand = LogDepthToExpandDefault = 2;
5027 ErrorCallback = NULL;
5028 ErrorCallbackUserData = NULL;
5030 ErrorCountCurrentFrame = 0;
5031 StackSizesInBeginForCurrentWindow = NULL;
5033 DebugDrawIdConflictsCount = 0;
5034 DebugLogFlags = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_OutputToTTY;
5036 DebugLogSkippedErrors = 0;
5037 DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
5038 DebugLogAutoDisableFrames = 0;
5039 DebugLocateFrames = 0;
5040 DebugBeginReturnValueCullDepth = -1;
5041 DebugItemPickerActive =
false;
5042 DebugItemPickerMouseButton = ImGuiMouseButton_Left;
5043 DebugItemPickerBreakId = 0;
5044 DebugFlashStyleColorTime = 0.0f;
5045 DebugFlashStyleColorIdx = ImGuiCol_COUNT;
5046 DebugHoveredDockNode = NULL;
5050 DebugBreakInWindow = 0;
5051 DebugBreakInTable = 0;
5052 DebugBreakInLocateId =
false;
5053 DebugBreakKeyChord = ImGuiKey_Pause;
5054 DebugBreakInShortcutRouting = ImGuiKey_None;
5056 memset(FramerateSecPerFrame, 0,
sizeof(FramerateSecPerFrame));
5057 FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
5058 FramerateSecPerFrameAccum = 0.0f;
5059 WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
5060 memset(TempKeychordName, 0,
sizeof(TempKeychordName));
5063void ImGui::Initialize()
5066 IM_ASSERT(!g.Initialized && !g.SettingsLoaded);
5071 ini_handler.TypeName =
"Window";
5072 ini_handler.TypeHash = ImHashStr(
"Window");
5073 ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
5074 ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
5075 ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
5076 ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
5077 ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll;
5078 AddSettingsHandler(&ini_handler);
5080 TableSettingsAddSettingsHandler();
5083 LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_ARRAYSIZE(GLocalizationEntriesEnUS));
5086 g.PlatformIO.Platform_GetClipboardTextFn =
5087 Platform_GetClipboardTextFn_DefaultImpl;
5088 g.PlatformIO.Platform_SetClipboardTextFn = Platform_SetClipboardTextFn_DefaultImpl;
5089 g.PlatformIO.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl;
5090 g.PlatformIO.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl;
5094 viewport->ID = IMGUI_VIEWPORT_DEFAULT_ID;
5096 viewport->PlatformWindowCreated =
true;
5097 viewport->Flags = ImGuiViewportFlags_OwnedByApp;
5098 g.Viewports.push_back(viewport);
5099 g.TempBuffer.resize(1024 * 3 + 1, 0);
5100 g.ViewportCreatedCount++;
5101 g.PlatformIO.Viewports.push_back(g.Viewports[0]);
5104 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
5105 if ((key >= ImGuiKey_0 && key <= ImGuiKey_9) || (key >= ImGuiKey_A && key <= ImGuiKey_Z) ||
5106 (key >= ImGuiKey_Keypad0 && key <= ImGuiKey_Keypad9) || key == ImGuiKey_Tab || key == ImGuiKey_Space ||
5107 key == ImGuiKey_Apostrophe || key == ImGuiKey_Comma || key == ImGuiKey_Minus || key == ImGuiKey_Period ||
5108 key == ImGuiKey_Slash || key == ImGuiKey_Semicolon || key == ImGuiKey_Equal ||
5109 key == ImGuiKey_LeftBracket || key == ImGuiKey_RightBracket || key == ImGuiKey_GraveAccent ||
5110 key == ImGuiKey_KeypadDecimal || key == ImGuiKey_KeypadDivide || key == ImGuiKey_KeypadMultiply ||
5111 key == ImGuiKey_KeypadSubtract || key == ImGuiKey_KeypadAdd || key == ImGuiKey_KeypadEqual)
5112 g.KeysMayBeCharInput.SetBit(key);
5114#ifdef IMGUI_HAS_DOCK
5116 DockContextInitialize(&g);
5119 g.Initialized =
true;
5123void ImGui::Shutdown()
5126 IM_ASSERT_USER_ERROR(g.IO.BackendPlatformUserData == NULL,
"Forgot to shutdown Platform backend?");
5127 IM_ASSERT_USER_ERROR(g.IO.BackendRendererUserData == NULL,
"Forgot to shutdown Renderer backend?");
5131 if (g.IO.Fonts && g.FontAtlasOwnedByContext)
5133 g.IO.Fonts->Locked =
false;
5134 IM_DELETE(g.IO.Fonts);
5137 g.DrawListSharedData.TempBuffer.clear();
5145 if (g.SettingsLoaded && g.IO.IniFilename != NULL)
5146 SaveIniSettingsToDisk(g.IO.IniFilename);
5149 DestroyPlatformWindows();
5152 DockContextShutdown(&g);
5154 CallContextHooks(&g, ImGuiContextHookType_Shutdown);
5157 g.Windows.clear_delete();
5158 g.WindowsFocusOrder.clear();
5159 g.WindowsTempSortBuffer.clear();
5160 g.CurrentWindow = NULL;
5161 g.CurrentWindowStack.clear();
5162 g.WindowsById.Clear();
5164 g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
5165 g.ActiveIdWindow = NULL;
5166 g.MovingWindow = NULL;
5168 g.KeysRoutingTable.Clear();
5170 g.ColorStack.clear();
5171 g.StyleVarStack.clear();
5172 g.FontStack.clear();
5173 g.OpenPopupStack.clear();
5174 g.BeginPopupStack.clear();
5175 g.TreeNodeStack.clear();
5177 g.CurrentViewport = g.MouseViewport = g.MouseLastHoveredViewport = NULL;
5178 g.Viewports.clear_delete();
5181 g.CurrentTabBarStack.clear();
5182 g.ShrinkWidthBuffer.clear();
5184 g.ClipperTempData.clear_destruct();
5187 g.TablesTempData.clear_destruct();
5188 g.DrawChannelsTempMergeBuffer.clear();
5190 g.MultiSelectStorage.Clear();
5191 g.MultiSelectTempData.clear_destruct();
5193 g.ClipboardHandlerData.clear();
5194 g.MenusIdSubmittedThisFrame.clear();
5195 g.InputTextState.ClearFreeMemory();
5196 g.InputTextDeactivatedState.ClearFreeMemory();
5198 g.SettingsWindows.clear();
5199 g.SettingsHandlers.clear();
5203#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
5204 if (g.LogFile != stdout)
5206 ImFileClose(g.LogFile);
5209 g.LogBuffer.clear();
5210 g.DebugLogBuf.clear();
5211 g.DebugLogIndex.clear();
5213 g.Initialized =
false;
5220 IM_ASSERT(hook->Callback != NULL && hook->HookId == 0 && hook->Type != ImGuiContextHookType_PendingRemoval_);
5221 g.Hooks.push_back(*hook);
5222 g.Hooks.back().HookId = ++g.HookIdNext;
5223 return g.HookIdNext;
5227void ImGui::RemoveContextHook(
ImGuiContext *ctx, ImGuiID hook_id)
5230 IM_ASSERT(hook_id != 0);
5232 if (hook.HookId == hook_id)
5233 hook.Type = ImGuiContextHookType_PendingRemoval_;
5238void ImGui::CallContextHooks(
ImGuiContext *ctx, ImGuiContextHookType hook_type)
5242 if (hook.Type == hook_type)
5243 hook.Callback(&g, &hook);
5251ImGuiWindow::ImGuiWindow(
ImGuiContext *ctx,
const char *name) : DrawListInst(NULL)
5253 memset(
this, 0,
sizeof(*
this));
5255 Name = ImStrdup(name);
5256 NameBufLen = (int)ImStrlen(name) + 1;
5257 ID = ImHashStr(name);
5258 IDStack.push_back(ID);
5259 ViewportAllowPlatformMonitorExtend = -1;
5260 ViewportPos =
ImVec2(FLT_MAX, FLT_MAX);
5261 MoveId = GetID(
"#MOVE");
5262 TabId = GetID(
"#TAB");
5263 ScrollTarget =
ImVec2(FLT_MAX, FLT_MAX);
5264 ScrollTargetCenterRatio =
ImVec2(0.5f, 0.5f);
5265 AutoFitFramesX = AutoFitFramesY = -1;
5266 AutoPosLastDirection = ImGuiDir_None;
5267 SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = SetWindowDockAllowFlags = 0;
5268 SetWindowPosVal = SetWindowPosPivot =
ImVec2(FLT_MAX, FLT_MAX);
5269 LastFrameActive = -1;
5270 LastFrameJustFocused = -1;
5271 LastTimeActive = -1.0f;
5273 FontWindowScale = FontWindowScaleParents = FontDpiScale = 1.0f;
5274 SettingsOffset = -1;
5276 DrawList = &DrawListInst;
5277 DrawList->_OwnerName = Name;
5278 DrawList->_Data = &Ctx->DrawListSharedData;
5279 NavPreferredScoringPosRel[0] = NavPreferredScoringPosRel[1] =
ImVec2(FLT_MAX, FLT_MAX);
5283ImGuiWindow::~ImGuiWindow()
5285 IM_ASSERT(DrawList == &DrawListInst);
5287 ColumnsStorage.clear_destruct();
5293 g.CurrentWindow = window;
5294 g.StackSizesInBeginForCurrentWindow = g.CurrentWindow ? &g.CurrentWindowStack.back().StackSizesInBegin : NULL;
5296 window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
5299 g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
5300 g.FontScale = g.DrawListSharedData.FontScale = g.FontSize / g.Font->FontSize;
5301 ImGui::NavUpdateCurrentWindowIsScrollPushableX();
5305void ImGui::GcCompactTransientMiscBuffers()
5308 g.ItemFlagsStack.clear();
5309 g.GroupStack.clear();
5310 g.MultiSelectTempDataStacked = 0;
5311 g.MultiSelectTempData.clear_destruct();
5312 TableGcCompactSettings();
5320void ImGui::GcCompactTransientWindowBuffers(
ImGuiWindow *window)
5322 window->MemoryCompacted =
true;
5323 window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity;
5324 window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity;
5325 window->IDStack.clear();
5326 window->DrawList->_ClearFreeMemory();
5327 window->DC.ChildWindows.clear();
5328 window->DC.ItemWidthStack.clear();
5329 window->DC.TextWrapPosStack.clear();
5332void ImGui::GcAwakeTransientWindowBuffers(
ImGuiWindow *window)
5336 window->MemoryCompacted =
false;
5337 window->DrawList->IdxBuffer.reserve(window->MemoryDrawListIdxCapacity);
5338 window->DrawList->VtxBuffer.reserve(window->MemoryDrawListVtxCapacity);
5339 window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0;
5342void ImGui::SetActiveID(ImGuiID
id,
ImGuiWindow *window)
5347 if (g.ActiveId != 0)
5352 if (g.MovingWindow != NULL && g.ActiveId == g.MovingWindow->MoveId)
5354 IMGUI_DEBUG_LOG_ACTIVEID(
"SetActiveID() cancel MovingWindow\n");
5355 g.MovingWindow = NULL;
5360 deactivated_data->ID = g.ActiveId;
5361 deactivated_data->ElapseFrame =
5362 (g.LastItemData.ID == g.ActiveId) ? g.FrameCount : g.FrameCount + 1;
5363 deactivated_data->HasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore;
5364 deactivated_data->IsAlive = (g.ActiveIdIsAlive == g.ActiveId);
5369 if (g.InputTextState.ID == g.ActiveId)
5370 InputTextDeactivateHook(g.ActiveId);
5374 g.ActiveIdIsJustActivated = (g.ActiveId != id);
5375 if (g.ActiveIdIsJustActivated)
5377 IMGUI_DEBUG_LOG_ACTIVEID(
"SetActiveID() old:0x%08X (window \"%s\") -> new:0x%08X (window \"%s\")\n", g.ActiveId,
5378 g.ActiveIdWindow ? g.ActiveIdWindow->Name :
"", id, window ? window->Name :
"");
5379 g.ActiveIdTimer = 0.0f;
5380 g.ActiveIdHasBeenPressedBefore =
false;
5381 g.ActiveIdHasBeenEditedBefore =
false;
5382 g.ActiveIdMouseButton = -1;
5385 g.LastActiveId = id;
5386 g.LastActiveIdTimer = 0.0f;
5390 g.ActiveIdAllowOverlap =
false;
5391 g.ActiveIdNoClearOnFocusLoss =
false;
5392 g.ActiveIdWindow = window;
5393 g.ActiveIdHasBeenEditedThisFrame =
false;
5394 g.ActiveIdFromShortcut =
false;
5397 g.ActiveIdIsAlive = id;
5399 (g.NavActivateId ==
id || g.NavJustMovedToId == id) ? g.NavInputSource : ImGuiInputSource_Mouse;
5400 IM_ASSERT(g.ActiveIdSource != ImGuiInputSource_None);
5405 g.ActiveIdUsingNavDirMask = 0x00;
5406 g.ActiveIdUsingAllKeyboardKeys =
false;
5409void ImGui::ClearActiveID()
5411 SetActiveID(0, NULL);
5414void ImGui::SetHoveredID(ImGuiID
id)
5418 g.HoveredIdAllowOverlap =
false;
5419 if (
id != 0 && g.HoveredIdPreviousFrame !=
id)
5420 g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f;
5423ImGuiID ImGui::GetHoveredID()
5426 return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame;
5429void ImGui::MarkItemEdited(ImGuiID
id)
5435 if (g.LastItemData.ItemFlags & ImGuiItemFlags_NoMarkEdited)
5437 if (g.ActiveId ==
id || g.ActiveId == 0)
5440 g.ActiveIdHasBeenEditedThisFrame =
true;
5441 g.ActiveIdHasBeenEditedBefore =
true;
5442 if (g.DeactivatedItemData.ID ==
id)
5443 g.DeactivatedItemData.HasBeenEditedBefore =
true;
5449 IM_ASSERT(g.DragDropActive || g.ActiveId ==
id || g.ActiveId == 0 || g.ActiveIdPreviousFrame ==
id ||
5450 (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
5453 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
5456bool ImGui::IsWindowContentHoverable(
ImGuiWindow *window, ImGuiHoveredFlags flags)
5462 if (
ImGuiWindow *focused_root_window = g.NavWindow->RootWindowDockTree)
5463 if (focused_root_window->WasActive && focused_root_window != window->RootWindowDockTree)
5467 bool want_inhibit =
false;
5468 if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
5469 want_inhibit =
true;
5470 else if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) &&
5471 !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
5472 want_inhibit =
true;
5476 if (!IsWindowWithinBeginStackOf(window->RootWindow, focused_root_window))
5481 if (window->Viewport != g.MouseViewport)
5482 if (g.MovingWindow == NULL || window->RootWindowDockTree != g.MovingWindow->RootWindowDockTree)
5488static inline float CalcDelayFromHoveredFlags(ImGuiHoveredFlags flags)
5491 if (flags & ImGuiHoveredFlags_DelayNormal)
5492 return g.Style.HoverDelayNormal;
5493 if (flags & ImGuiHoveredFlags_DelayShort)
5494 return g.Style.HoverDelayShort;
5498static ImGuiHoveredFlags ApplyHoverFlagsForTooltip(ImGuiHoveredFlags user_flags, ImGuiHoveredFlags shared_flags)
5501 if (user_flags & (ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal))
5502 shared_flags &= ~(ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal);
5503 return user_flags | shared_flags;
5510bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
5514 IM_ASSERT_USER_ERROR((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0,
5515 "Invalid flags for IsItemHovered()!");
5517 if (g.NavHighlightItemUnderNav && g.NavCursorVisible && !(flags & ImGuiHoveredFlags_NoNavOverride))
5519 if (!IsItemFocused())
5521 if ((g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
5524 if (flags & ImGuiHoveredFlags_ForTooltip)
5525 flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipNav);
5530 ImGuiItemStatusFlags status_flags = g.LastItemData.StatusFlags;
5531 if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
5534 if (flags & ImGuiHoveredFlags_ForTooltip)
5535 flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipMouse);
5544 if (g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0)
5545 if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByWindow) == 0)
5549 const ImGuiID
id = g.LastItemData.ID;
5550 if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
5551 if (g.ActiveId != 0 && g.ActiveId !=
id && !g.ActiveIdAllowOverlap)
5552 if (g.ActiveId != window->MoveId && g.ActiveId != window->TabId)
5557 if (!IsWindowContentHoverable(window, flags) &&
5558 !(g.LastItemData.ItemFlags & ImGuiItemFlags_NoWindowHoverableCheck))
5562 if ((g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
5568 if (
id == window->MoveId && window->WriteAccessed)
5572 if ((g.LastItemData.ItemFlags & ImGuiItemFlags_AllowOverlap) &&
id != 0)
5573 if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByItem) == 0)
5574 if (g.HoveredIdPreviousFrame != g.LastItemData.ID)
5580 const float delay = CalcDelayFromHoveredFlags(flags);
5581 if (delay > 0.0f || (flags & ImGuiHoveredFlags_Stationary))
5583 ImGuiID hover_delay_id =
5584 (g.LastItemData.ID != 0) ? g.LastItemData.ID : window->GetIDFromPos(g.LastItemData.Rect.Min);
5585 if ((flags & ImGuiHoveredFlags_NoSharedDelay) && (g.HoverItemDelayIdPreviousFrame != hover_delay_id))
5586 g.HoverItemDelayTimer = 0.0f;
5587 g.HoverItemDelayId = hover_delay_id;
5594 if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverItemUnlockedStationaryId != hover_delay_id)
5597 if (g.HoverItemDelayTimer < delay)
5611bool ImGui::ItemHoverable(
const ImRect &bb, ImGuiID
id, ImGuiItemFlags item_flags)
5617#ifndef IMGUI_DISABLE_DEBUG_TOOLS
5618 if (
id != 0 && g.HoveredIdPreviousFrame ==
id && (item_flags & ImGuiItemFlags_AllowDuplicateId) == 0)
5620 g.HoveredIdPreviousFrameItemCount++;
5621 if (g.DebugDrawIdConflicts ==
id)
5622 window->DrawList->AddRect(bb.Min -
ImVec2(1, 1), bb.Max +
ImVec2(1, 1), IM_COL32(255, 0, 0, 255), 0.0f,
5623 ImDrawFlags_None, 2.0f);
5627 if (g.HoveredWindow != window)
5629 if (!IsMouseHoveringRect(bb.Min, bb.Max))
5632 if (g.HoveredId != 0 && g.HoveredId !=
id && !g.HoveredIdAllowOverlap)
5634 if (g.ActiveId != 0 && g.ActiveId !=
id && !g.ActiveIdAllowOverlap)
5635 if (!g.ActiveIdFromShortcut)
5639 if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) &&
5640 !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
5642 g.HoveredIdIsDisabled =
true;
5651 if (g.DragDropActive && g.DragDropPayload.SourceId ==
id &&
5652 !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover))
5660 if (item_flags & ImGuiItemFlags_AllowOverlap)
5662 g.HoveredIdAllowOverlap =
true;
5663 if (g.HoveredIdPreviousFrame !=
id)
5669 if (
id == g.LastItemData.ID && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasShortcut) &&
5671 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal))
5672 SetTooltip(
"%s", GetKeyChordName(g.LastItemData.Shortcut));
5676 if (item_flags & ImGuiItemFlags_Disabled)
5679 if (g.ActiveId ==
id &&
id != 0)
5681 g.HoveredIdIsDisabled =
true;
5685#ifndef IMGUI_DISABLE_DEBUG_TOOLS
5692 if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame ==
id)
5693 GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
5694 if (g.DebugItemPickerBreakId ==
id)
5699 if (g.NavHighlightItemUnderNav && (item_flags & ImGuiItemFlags_NoNavDisableMouseHover) == 0)
5707bool ImGui::IsClippedEx(
const ImRect &bb, ImGuiID
id)
5711 if (!bb.Overlaps(window->ClipRect))
5712 if (
id == 0 || (
id != g.ActiveId &&
id != g.ActiveIdPreviousFrame &&
id != g.NavId &&
id != g.NavActivateId))
5713 if (!g.ItemUnclipByLog)
5720void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags item_flags, ImGuiItemStatusFlags status_flags,
5724 g.LastItemData.ID = item_id;
5725 g.LastItemData.ItemFlags = item_flags;
5726 g.LastItemData.StatusFlags = status_flags;
5727 g.LastItemData.Rect = g.LastItemData.NavRect = item_rect;
5730static void ImGui::SetLastItemDataForWindow(
ImGuiWindow *window,
const ImRect &rect)
5733 if (window->DockIsActive)
5734 SetLastItemData(window->MoveId, g.CurrentItemFlags, window->DC.DockTabItemStatusFlags,
5735 window->DC.DockTabItemRect);
5737 SetLastItemData(window->MoveId, g.CurrentItemFlags, window->DC.WindowItemStatusFlags, rect);
5740static void ImGui::SetLastItemDataForChildWindowItem(
ImGuiWindow *window,
const ImRect &rect)
5743 SetLastItemData(window->ChildId, g.CurrentItemFlags, window->DC.ChildItemStatusFlags, rect);
5746float ImGui::CalcWrapWidthForPos(
const ImVec2 &pos,
float wrap_pos_x)
5748 if (wrap_pos_x < 0.0f)
5753 if (wrap_pos_x == 0.0f)
5760 wrap_pos_x = window->WorkRect.Max.x;
5762 else if (wrap_pos_x > 0.0f)
5764 wrap_pos_x += window->Pos.x - window->Scroll.x;
5767 return ImMax(wrap_pos_x - pos.x, 1.0f);
5771void *ImGui::MemAlloc(
size_t size)
5773 void *ptr = (*GImAllocatorAllocFunc)(size, GImAllocatorUserData);
5774#ifndef IMGUI_DISABLE_DEBUG_TOOLS
5776 DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, size);
5782void ImGui::MemFree(
void *ptr)
5784#ifndef IMGUI_DISABLE_DEBUG_TOOLS
5787 DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, (
size_t)-1);
5789 return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
5794void ImGui::DebugAllocHook(
ImGuiDebugAllocInfo *info,
int frame_count,
void *ptr,
size_t size)
5798 if (entry->FrameCount != frame_count)
5800 info->LastEntriesIdx = (info->LastEntriesIdx + 1) % IM_ARRAYSIZE(info->LastEntriesBuf);
5801 entry = &info->LastEntriesBuf[info->LastEntriesIdx];
5802 entry->FrameCount = frame_count;
5803 entry->AllocCount = entry->FreeCount = 0;
5805 if (size != (
size_t)-1)
5808 entry->AllocCount++;
5809 info->TotalAllocCount++;
5815 info->TotalFreeCount++;
5819const char *ImGui::GetClipboardText()
5822 return g.PlatformIO.Platform_GetClipboardTextFn ? g.PlatformIO.Platform_GetClipboardTextFn(&g) :
"";
5825void ImGui::SetClipboardText(
const char *text)
5828 if (g.PlatformIO.Platform_SetClipboardTextFn != NULL)
5829 g.PlatformIO.Platform_SetClipboardTextFn(&g, text);
5832const char *ImGui::GetVersion()
5834 return IMGUI_VERSION;
5839 IM_ASSERT(GImGui != NULL &&
5840 "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
5847 IM_ASSERT(ctx != NULL);
5853 IM_ASSERT(GImGui != NULL &&
5854 "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext()?");
5855 return GImGui->PlatformIO;
5861 IM_ASSERT(ctx != NULL);
5862 return ctx->PlatformIO;
5870 return viewport->DrawDataP.Valid ? &viewport->DrawDataP : NULL;
5873double ImGui::GetTime()
5875 return GImGui->Time;
5878int ImGui::GetFrameCount()
5880 return GImGui->FrameCount;
5887 IM_ASSERT(drawlist_no < IM_ARRAYSIZE(viewport->BgFgDrawLists));
5888 ImDrawList *draw_list = viewport->BgFgDrawLists[drawlist_no];
5889 if (draw_list == NULL)
5891 draw_list = IM_NEW(
ImDrawList)(&g.DrawListSharedData);
5892 draw_list->_OwnerName = drawlist_name;
5893 viewport->BgFgDrawLists[drawlist_no] = draw_list;
5897 if (viewport->BgFgDrawListsLastFrame[drawlist_no] != g.FrameCount)
5899 draw_list->_ResetForNewFrame();
5900 draw_list->PushTextureID(g.IO.Fonts->TexID);
5901 draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size,
false);
5902 viewport->BgFgDrawListsLastFrame[drawlist_no] = g.FrameCount;
5909 if (viewport == NULL)
5910 viewport = GImGui->CurrentWindow->Viewport;
5911 return GetViewportBgFgDrawList((
ImGuiViewportP *)viewport, 0,
"##Background");
5916 if (viewport == NULL)
5917 viewport = GImGui->CurrentWindow->Viewport;
5918 return GetViewportBgFgDrawList((
ImGuiViewportP *)viewport, 1,
"##Foreground");
5923 return &GImGui->DrawListSharedData;
5926void ImGui::StartMouseMovingWindow(
ImGuiWindow *window)
5933 FocusWindow(window);
5934 SetActiveID(window->MoveId, window);
5935 if (g.IO.ConfigNavCursorVisibleAuto)
5936 g.NavCursorVisible =
false;
5937 g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindowDockTree->Pos;
5938 g.ActiveIdNoClearOnFocusLoss =
true;
5939 SetActiveIdUsingAllKeyboardKeys();
5941 bool can_move_window =
true;
5942 if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoMove))
5943 can_move_window =
false;
5945 if (node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove))
5946 can_move_window =
false;
5947 if (can_move_window)
5948 g.MovingWindow = window;
5956 bool can_undock_node =
false;
5957 if (undock && node != NULL && node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove) == 0 &&
5958 (node->MergedFlags & ImGuiDockNodeFlags_NoUndocking) == 0)
5966 if (root_node->OnlyNodeWithWindows != node ||
5967 root_node->CentralNode !=
5969 can_undock_node =
true;
5972 const bool clicked = IsMouseClicked(0);
5973 const bool dragging = IsMouseDragging(0);
5974 if (can_undock_node && dragging)
5975 DockContextQueueUndockNode(
5978 else if (!can_undock_node && (clicked || dragging) && g.MovingWindow != window)
5979 StartMouseMovingWindow(window);
5989void ImGui::UpdateMouseMovingWindowNewFrame()
5992 if (g.MovingWindow != NULL)
5997 KeepAliveID(g.ActiveId);
5998 IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindowDockTree);
5999 ImGuiWindow *moving_window = g.MovingWindow->RootWindowDockTree;
6002 const bool window_disappared = (!moving_window->WasActive && !moving_window->Active);
6003 if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos) && !window_disappared)
6005 ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset;
6006 if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
6008 SetWindowPos(moving_window, pos, ImGuiCond_Always);
6009 if (moving_window->Viewport &&
6010 moving_window->ViewportOwned)
6013 moving_window->Viewport->Pos = pos;
6014 moving_window->Viewport->UpdateWorkRect();
6017 FocusWindow(g.MovingWindow);
6021 if (!window_disappared)
6026 if (g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
6027 UpdateTryMergeWindowIntoHostViewport(moving_window, g.MouseViewport);
6031 if (moving_window->Viewport && !IsDragDropPayloadBeingAccepted())
6032 g.MouseViewport = moving_window->Viewport;
6035 if (moving_window->Viewport)
6036 moving_window->Viewport->Flags &= ~ImGuiViewportFlags_NoInputs;
6039 g.MovingWindow = NULL;
6047 if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId)
6049 KeepAliveID(g.ActiveId);
6050 if (!g.IO.MouseDown[0])
6059void ImGui::UpdateMouseMovingWindowEndFrame()
6062 if (g.ActiveId != 0 || (g.HoveredId != 0 && !g.HoveredIdIsDisabled))
6066 if (g.NavWindow && g.NavWindow->Appearing)
6072 if (g.IO.MouseClicked[0])
6077 ImGuiWindow *root_window = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
6078 const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) &&
6079 !IsPopupOpen(root_window->PopupId, ImGuiPopupFlags_AnyPopupLevel);
6081 if (root_window != NULL && !is_closed_popup)
6083 StartMouseMovingWindow(g.HoveredWindow);
6086 if (g.IO.ConfigWindowsMoveFromTitleBarOnly)
6087 if (!(root_window->Flags & ImGuiWindowFlags_NoTitleBar) || root_window->DockIsActive)
6088 if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
6089 g.MovingWindow = NULL;
6094 if (g.HoveredIdIsDisabled)
6095 g.MovingWindow = NULL;
6097 else if (root_window == NULL && g.NavWindow != NULL)
6100 FocusWindow(NULL, ImGuiFocusRequestFlags_UnlessBelowModal);
6108 if (g.IO.MouseClicked[1] && g.HoveredId == 0)
6113 bool hovered_window_above_modal = g.HoveredWindow && (modal == NULL || IsWindowAbove(g.HoveredWindow, modal));
6114 ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal, true);
6122 window->Pos += delta;
6123 window->ClipRect.Translate(delta);
6124 window->OuterRectClipped.Translate(delta);
6125 window->InnerRect.Translate(delta);
6126 window->DC.CursorPos += delta;
6127 window->DC.CursorStartPos += delta;
6128 window->DC.CursorMaxPos += delta;
6129 window->DC.IdealMaxPos += delta;
6132static void ScaleWindow(
ImGuiWindow *window,
float scale)
6134 ImVec2 origin = window->Viewport->Pos;
6135 window->Pos = ImFloor((window->Pos - origin) * scale + origin);
6136 window->Size = ImTrunc(window->Size * scale);
6137 window->SizeFull = ImTrunc(window->SizeFull * scale);
6138 window->ContentSize = ImTrunc(window->ContentSize * scale);
6141static bool IsWindowActiveAndVisible(
ImGuiWindow *window)
6143 return (window->Active) && (!window->Hidden);
6148void ImGui::UpdateHoveredWindowAndCaptureFlags(
const ImVec2 &mouse_pos)
6155 g.WindowsBorderHoverPadding =
6156 ImMax(ImMax(g.Style.TouchExtraPadding.x, g.Style.TouchExtraPadding.y), g.Style.WindowBorderHoverPadding);
6165 bool clear_hovered_windows =
false;
6166 FindHoveredWindowEx(mouse_pos,
false, &g.HoveredWindow, &g.HoveredWindowUnderMovingWindow);
6167 IM_ASSERT(g.HoveredWindow == NULL || g.HoveredWindow == g.MovingWindow ||
6168 g.HoveredWindow->Viewport == g.MouseViewport);
6169 g.HoveredWindowBeforeClear = g.HoveredWindow;
6172 ImGuiWindow *modal_window = GetTopMostPopupModal();
6173 if (modal_window && g.HoveredWindow &&
6174 !IsWindowWithinBeginStackOf(g.HoveredWindow->RootWindow, modal_window))
6175 clear_hovered_windows =
true;
6178 if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
6179 clear_hovered_windows =
true;
6183 const bool has_open_popup = (g.OpenPopupStack.Size > 0);
6184 const bool has_open_modal = (modal_window != NULL);
6185 int mouse_earliest_down = -1;
6186 bool mouse_any_down =
false;
6187 for (
int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
6189 if (io.MouseClicked[i])
6191 io.MouseDownOwned[i] = (g.HoveredWindow != NULL) || has_open_popup;
6192 io.MouseDownOwnedUnlessPopupClose[i] = (g.HoveredWindow != NULL) || has_open_modal;
6194 mouse_any_down |= io.MouseDown[i];
6195 if (io.MouseDown[i] ||
6196 io.MouseReleased[i])
6197 if (mouse_earliest_down == -1 || io.MouseClickedTime[i] < io.MouseClickedTime[mouse_earliest_down])
6198 mouse_earliest_down = i;
6200 const bool mouse_avail = (mouse_earliest_down == -1) || io.MouseDownOwned[mouse_earliest_down];
6201 const bool mouse_avail_unless_popup_close =
6202 (mouse_earliest_down == -1) || io.MouseDownOwnedUnlessPopupClose[mouse_earliest_down];
6207 const bool mouse_dragging_extern_payload =
6208 g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
6209 if (!mouse_avail && !mouse_dragging_extern_payload)
6210 clear_hovered_windows =
true;
6212 if (clear_hovered_windows)
6213 g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
6218 if (g.WantCaptureMouseNextFrame != -1)
6220 io.WantCaptureMouse = io.WantCaptureMouseUnlessPopupClose = (g.WantCaptureMouseNextFrame != 0);
6224 io.WantCaptureMouse = (mouse_avail && (g.HoveredWindow != NULL || mouse_any_down)) || has_open_popup;
6225 io.WantCaptureMouseUnlessPopupClose =
6226 (mouse_avail_unless_popup_close && (g.HoveredWindow != NULL || mouse_any_down)) || has_open_modal;
6231 io.WantCaptureKeyboard =
false;
6232 if ((io.ConfigFlags & ImGuiConfigFlags_NoKeyboard) == 0)
6234 if ((g.ActiveId != 0) || (modal_window != NULL))
6235 io.WantCaptureKeyboard =
true;
6236 else if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && io.ConfigNavCaptureKeyboard)
6237 io.WantCaptureKeyboard =
true;
6239 if (g.WantCaptureKeyboardNextFrame != -1)
6240 io.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0);
6244 io.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) :
false;
6249static void SetupDrawListSharedData()
6252 ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
6254 virtual_space.Add(viewport->GetMainRect());
6255 g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
6256 g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
6257 g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError);
6258 g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
6259 if (g.Style.AntiAliasedLines)
6260 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines;
6261 if (g.Style.AntiAliasedLinesUseTex && !(g.IO.Fonts->Flags & ImFontAtlasFlags_NoBakedLines))
6262 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex;
6263 if (g.Style.AntiAliasedFill)
6264 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
6265 if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
6266 g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
6267 g.DrawListSharedData.InitialFringeScale = 1.0f;
6270void ImGui::NewFrame()
6272 IM_ASSERT(GImGui != NULL &&
6273 "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
6278 for (
int n = g.Hooks.Size - 1; n >= 0; n--)
6279 if (g.Hooks[n].Type == ImGuiContextHookType_PendingRemoval_)
6280 g.Hooks.erase(&g.Hooks[n]);
6282 CallContextHooks(&g, ImGuiContextHookType_NewFramePre);
6285 g.ConfigFlagsLastFrame = g.ConfigFlagsCurrFrame;
6286 ErrorCheckNewFrameSanityChecks();
6287 g.ConfigFlagsCurrFrame = g.IO.ConfigFlags;
6292 g.Time += g.IO.DeltaTime;
6293 g.WithinFrameScope =
true;
6295 g.TooltipOverrideCount = 0;
6296 g.WindowsActiveCount = 0;
6297 g.MenusIdSubmittedThisFrame.resize(0);
6300 g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];
6301 g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;
6302 g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
6303 g.FramerateSecPerFrameCount = ImMin(g.FramerateSecPerFrameCount + 1, IM_ARRAYSIZE(g.FramerateSecPerFrame));
6304 g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f)
6305 ? (1.0f / (g.FramerateSecPerFrameAccum / (
float)g.FramerateSecPerFrameCount))
6309 g.InputEventsTrail.resize(0);
6310 UpdateInputEvents(g.IO.ConfigInputTrickleEventQueue);
6313 UpdateViewportsNewFrame();
6317 g.IO.Fonts->Locked =
true;
6318 SetupDrawListSharedData();
6319 SetCurrentFont(GetDefaultFont());
6320 IM_ASSERT(g.Font->IsLoaded());
6325 viewport->DrawData = NULL;
6326 viewport->DrawDataP.Valid =
false;
6330 if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId)
6331 KeepAliveID(g.DragDropPayload.SourceId);
6334 if (!g.IO.ConfigDebugHighlightIdConflicts || !g.IO.KeyCtrl)
6335 g.DebugDrawIdConflicts = 0;
6336 if (g.IO.ConfigDebugHighlightIdConflicts && g.HoveredIdPreviousFrameItemCount > 1)
6337 g.DebugDrawIdConflicts = g.HoveredIdPreviousFrame;
6340 if (!g.HoveredIdPreviousFrame)
6341 g.HoveredIdTimer = 0.0f;
6342 if (!g.HoveredIdPreviousFrame || (g.HoveredId && g.ActiveId == g.HoveredId))
6343 g.HoveredIdNotActiveTimer = 0.0f;
6345 g.HoveredIdTimer += g.IO.DeltaTime;
6346 if (g.HoveredId && g.ActiveId != g.HoveredId)
6347 g.HoveredIdNotActiveTimer += g.IO.DeltaTime;
6348 g.HoveredIdPreviousFrame = g.HoveredId;
6349 g.HoveredIdPreviousFrameItemCount = 0;
6351 g.HoveredIdAllowOverlap =
false;
6352 g.HoveredIdIsDisabled =
false;
6357 if (g.ActiveId != 0 && g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId)
6359 IMGUI_DEBUG_LOG_ACTIVEID(
"NewFrame(): ClearActiveID() because it isn't marked alive anymore!\n");
6365 g.ActiveIdTimer += g.IO.DeltaTime;
6366 g.LastActiveIdTimer += g.IO.DeltaTime;
6367 g.ActiveIdPreviousFrame = g.ActiveId;
6368 g.ActiveIdIsAlive = 0;
6369 g.ActiveIdHasBeenEditedThisFrame =
false;
6370 g.ActiveIdIsJustActivated =
false;
6371 if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
6373 if (g.ActiveId == 0)
6375 g.ActiveIdUsingNavDirMask = 0x00;
6376 g.ActiveIdUsingAllKeyboardKeys =
false;
6378 if (g.DeactivatedItemData.ElapseFrame < g.FrameCount)
6379 g.DeactivatedItemData.ID = 0;
6380 g.DeactivatedItemData.IsAlive =
false;
6386 if (g.HoverItemDelayId != 0 && g.MouseStationaryTimer >= g.Style.HoverStationaryDelay)
6387 g.HoverItemUnlockedStationaryId = g.HoverItemDelayId;
6388 else if (g.HoverItemDelayId == 0)
6389 g.HoverItemUnlockedStationaryId = 0;
6390 if (g.HoveredWindow != NULL && g.MouseStationaryTimer >= g.Style.HoverStationaryDelay)
6391 g.HoverWindowUnlockedStationaryId = g.HoveredWindow->ID;
6392 else if (g.HoveredWindow == NULL)
6393 g.HoverWindowUnlockedStationaryId = 0;
6396 g.HoverItemDelayIdPreviousFrame = g.HoverItemDelayId;
6397 if (g.HoverItemDelayId != 0)
6399 g.HoverItemDelayTimer += g.IO.DeltaTime;
6400 g.HoverItemDelayClearTimer = 0.0f;
6401 g.HoverItemDelayId = 0;
6403 else if (g.HoverItemDelayTimer > 0.0f)
6408 g.HoverItemDelayClearTimer += g.IO.DeltaTime;
6409 if (g.HoverItemDelayClearTimer >=
6410 ImMax(0.25f, g.IO.DeltaTime * 2.0f))
6411 g.HoverItemDelayTimer = g.HoverItemDelayClearTimer =
6417 g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr;
6418 g.DragDropAcceptIdCurr = 0;
6419 g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
6420 g.DragDropWithinSource =
false;
6421 g.DragDropWithinTarget =
false;
6422 g.DragDropHoldJustPressedId = 0;
6423 g.TooltipPreviousWindow = NULL;
6430 UpdateKeyboardInputs();
6441 UpdateMouseInputs();
6446 DockContextNewFrameUpdateUndocking(&g);
6449 IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
6450 const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f)
6452 : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
6455 window->WasActive = window->Active;
6456 window->Active =
false;
6457 window->WriteAccessed =
false;
6458 window->BeginCountPreviousFrame = window->BeginCount;
6459 window->BeginCount = 0;
6462 if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
6463 GcCompactTransientWindowBuffers(window);
6469 UpdateHoveredWindowAndCaptureFlags(g.IO.MousePos);
6472 UpdateMouseMovingWindowNewFrame();
6475 if (GetTopMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f))
6476 g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f);
6478 g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f);
6480 g.MouseCursor = ImGuiMouseCursor_Arrow;
6481 g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1;
6484 g.PlatformImeDataPrev = g.PlatformImeData;
6485 g.PlatformImeData.WantVisible =
false;
6491 for (
int i = 0; i < g.TablesLastTimeActive.Size; i++)
6492 if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time)
6493 TableGcCompactTransientBuffers(g.Tables.GetByIndex(i));
6495 if (table_temp_data.LastTimeActive >= 0.0f && table_temp_data.LastTimeActive < memory_compact_start_time)
6496 TableGcCompactTransientBuffers(&table_temp_data);
6498 GcCompactTransientMiscBuffers();
6499 g.GcCompactAll =
false;
6502 if (g.NavWindow && !g.NavWindow->WasActive)
6503 FocusTopMostWindowUnderOne(NULL, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild);
6508 g.CurrentWindowStack.resize(0);
6509 g.BeginPopupStack.resize(0);
6510 g.ItemFlagsStack.resize(0);
6511 g.ItemFlagsStack.push_back(ImGuiItemFlags_AutoClosePopups);
6512 g.CurrentItemFlags = g.ItemFlagsStack.back();
6513 g.GroupStack.resize(0);
6516 DockContextNewFrameUpdateDocking(&g);
6519#ifndef IMGUI_DISABLE_DEBUG_TOOLS
6520 UpdateDebugToolItemPicker();
6521 UpdateDebugToolStackQueries();
6522 UpdateDebugToolFlashStyleColor();
6523 if (g.DebugLocateFrames > 0 && --g.DebugLocateFrames == 0)
6525 g.DebugLocateId = 0;
6526 g.DebugBreakInLocateId =
false;
6528 if (g.DebugLogAutoDisableFrames > 0 && --g.DebugLogAutoDisableFrames == 0)
6530 DebugLog(
"(Debug Log: Auto-disabled some ImGuiDebugLogFlags after 2 frames)\n");
6531 g.DebugLogFlags &= ~g.DebugLogAutoDisableFlags;
6532 g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
6539 g.WithinFrameScopeWithImplicitWindow =
true;
6540 SetNextWindowSize(
ImVec2(400, 400), ImGuiCond_FirstUseEver);
6541 Begin(
"Debug##Default");
6542 IM_ASSERT(g.CurrentWindow->IsFallbackWindow ==
true);
6545 g.ErrorCountCurrentFrame = 0;
6546 ErrorRecoveryStoreState(&g.StackSizesInNewFrame);
6550#ifndef IMGUI_DISABLE_DEBUG_TOOLS
6551 if (g.IO.ConfigDebugBeginReturnValueLoop)
6552 g.DebugBeginReturnValueCullDepth =
6553 (g.DebugBeginReturnValueCullDepth == -1)
6555 : ((g.DebugBeginReturnValueCullDepth + ((g.FrameCount % 4) == 0 ? 1 : 0)) % 10);
6557 g.DebugBeginReturnValueCullDepth = -1;
6560 CallContextHooks(&g, ImGuiContextHookType_NewFramePost);
6564static int IMGUI_CDECL ChildWindowComparer(
const void *lhs,
const void *rhs)
6568 if (
int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))
6570 if (
int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
6572 return (a->BeginOrderWithinParent - b->BeginOrderWithinParent);
6577 out_sorted_windows->push_back(window);
6580 int count = window->DC.ChildWindows.Size;
6581 ImQsort(window->DC.ChildWindows.Data, (
size_t)count,
sizeof(
ImGuiWindow *), ChildWindowComparer);
6582 for (
int i = 0; i < count; i++)
6586 AddWindowToSortBuffer(out_sorted_windows, child);
6591static void AddWindowToDrawData(
ImGuiWindow *window,
int layer)
6595 IM_ASSERT(viewport != NULL);
6596 g.IO.MetricsRenderWindows++;
6597 if (window->DrawList->_Splitter._Count > 1)
6598 window->DrawList->ChannelsMerge();
6600 ImGui::AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[layer], window->DrawList);
6601 for (
ImGuiWindow *child : window->DC.ChildWindows)
6602 if (IsWindowActiveAndVisible(child))
6603 AddWindowToDrawData(child, layer);
6606static inline int GetWindowDisplayLayer(
ImGuiWindow *window)
6608 return (window->Flags & ImGuiWindowFlags_Tooltip) ? 1 : 0;
6612static inline void AddRootWindowToDrawData(
ImGuiWindow *window)
6614 AddWindowToDrawData(window, GetWindowDisplayLayer(window));
6619 int n = builder->Layers[0]->Size;
6621 for (
int i = 1; i < IM_ARRAYSIZE(builder->Layers); i++)
6622 full_size += builder->Layers[i]->Size;
6623 builder->Layers[0]->resize(full_size);
6624 for (
int layer_n = 1; layer_n < IM_ARRAYSIZE(builder->Layers); layer_n++)
6629 memcpy(builder->Layers[0]->Data + n, layer->Data, layer->Size *
sizeof(
ImDrawList *));
6638 ImDrawData *draw_data = &viewport->DrawDataP;
6640 viewport->DrawData = draw_data;
6641 viewport->DrawDataBuilder.Layers[0] = &draw_data->CmdLists;
6642 viewport->DrawDataBuilder.Layers[1] = &viewport->DrawDataBuilder.LayerData1;
6643 viewport->DrawDataBuilder.Layers[0]->resize(0);
6644 viewport->DrawDataBuilder.Layers[1]->resize(0);
6651 const bool is_minimized = (viewport->Flags & ImGuiViewportFlags_IsMinimized) != 0;
6653 draw_data->Valid =
true;
6654 draw_data->CmdListsCount = 0;
6655 draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
6656 draw_data->DisplayPos = viewport->Pos;
6657 draw_data->DisplaySize = is_minimized ?
ImVec2(0.0f, 0.0f) : viewport->Size;
6658 draw_data->FramebufferScale =
6659 io.DisplayFramebufferScale;
6660 draw_data->OwnerViewport = viewport;
6671void ImGui::PushClipRect(
const ImVec2 &clip_rect_min,
const ImVec2 &clip_rect_max,
6672 bool intersect_with_current_clip_rect)
6675 window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
6676 window->ClipRect = window->DrawList->_ClipRectStack.back();
6679void ImGui::PopClipRect()
6682 window->DrawList->PopClipRect();
6683 window->ClipRect = window->DrawList->_ClipRectStack.back();
6688 for (
int n = window->DC.ChildWindows.Size - 1; n >= 0; n--)
6689 if (IsWindowActiveAndVisible(window->DC.ChildWindows[n]))
6690 return FindFrontMostVisibleChildWindow(window->DC.ChildWindows[n]);
6694static void ImGui::RenderDimmedBackgroundBehindWindow(
ImGuiWindow *window, ImU32 col)
6696 if ((col & IM_COL32_A_MASK) == 0)
6700 ImRect viewport_rect = viewport->GetMainRect();
6707 ImDrawList *draw_list = window->RootWindowDockTree->DrawList;
6708 draw_list->ChannelsMerge();
6709 if (draw_list->CmdBuffer.Size == 0)
6710 draw_list->AddDrawCmd();
6711 draw_list->PushClipRect(viewport_rect.Min -
ImVec2(1, 1), viewport_rect.Max +
ImVec2(1, 1),
6714 draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col);
6715 ImDrawCmd cmd = draw_list->CmdBuffer.back();
6716 IM_ASSERT(cmd.ElemCount == 6);
6717 draw_list->CmdBuffer.pop_back();
6718 draw_list->CmdBuffer.push_front(cmd);
6719 draw_list->AddDrawCmd();
6721 draw_list->PopClipRect();
6725 if (window->RootWindow->DockIsActive)
6727 ImDrawList *draw_list = FindFrontMostVisibleChildWindow(window->RootWindowDockTree)->DrawList;
6728 draw_list->ChannelsMerge();
6729 if (draw_list->CmdBuffer.Size == 0)
6730 draw_list->AddDrawCmd();
6731 draw_list->PushClipRect(viewport_rect.Min, viewport_rect.Max,
false);
6732 RenderRectFilledWithHole(draw_list, window->RootWindowDockTree->Rect(), window->RootWindow->Rect(), col,
6734 draw_list->PopClipRect();
6741 ImGuiWindow *bottom_most_visible_window = parent_window;
6742 for (
int i = FindWindowDisplayIndex(parent_window); i >= 0; i--)
6745 if (window->Flags & ImGuiWindowFlags_ChildWindow)
6747 if (!IsWindowWithinBeginStackOf(window, parent_window))
6749 if (IsWindowActiveAndVisible(window) && GetWindowDisplayLayer(window) <= GetWindowDisplayLayer(parent_window))
6750 bottom_most_visible_window = window;
6752 return bottom_most_visible_window;
6758static void ImGui::RenderDimmedBackgrounds()
6761 ImGuiWindow *modal_window = GetTopMostAndVisiblePopupModal();
6762 if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f)
6764 const bool dim_bg_for_modal = (modal_window != NULL);
6765 const bool dim_bg_for_window_list = (g.NavWindowingTargetAnim != NULL && g.NavWindowingTargetAnim->Active);
6766 if (!dim_bg_for_modal && !dim_bg_for_window_list)
6770 if (dim_bg_for_modal)
6773 ImGuiWindow *dim_behind_window = FindBottomMostVisibleWindowWithinBeginStack(modal_window);
6774 RenderDimmedBackgroundBehindWindow(dim_behind_window,
6775 GetColorU32(modal_window->DC.ModalDimBgColor, g.DimBgRatio));
6776 viewports_already_dimmed[0] = modal_window->Viewport;
6778 else if (dim_bg_for_window_list)
6781 RenderDimmedBackgroundBehindWindow(g.NavWindowingTargetAnim,
6782 GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio));
6783 if (g.NavWindowingListWindow != NULL && g.NavWindowingListWindow->Viewport &&
6784 g.NavWindowingListWindow->Viewport != g.NavWindowingTargetAnim->Viewport)
6785 RenderDimmedBackgroundBehindWindow(g.NavWindowingListWindow,
6786 GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio));
6787 viewports_already_dimmed[0] = g.NavWindowingTargetAnim->Viewport;
6788 viewports_already_dimmed[1] = g.NavWindowingListWindow ? g.NavWindowingListWindow->Viewport : NULL;
6793 float distance = g.FontSize;
6794 ImRect bb = window->Rect();
6795 bb.Expand(distance);
6796 if (bb.GetWidth() >= viewport->Size.x && bb.GetHeight() >= viewport->Size.y)
6797 bb.Expand(-distance - 1.0f);
6798 window->DrawList->ChannelsMerge();
6799 if (window->DrawList->CmdBuffer.Size == 0)
6800 window->DrawList->AddDrawCmd();
6801 window->DrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size);
6802 window->DrawList->AddRect(bb.Min, bb.Max,
6803 GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha),
6804 window->WindowRounding, 0, 3.0f);
6805 window->DrawList->PopClipRect();
6811 if (viewport == viewports_already_dimmed[0] || viewport == viewports_already_dimmed[1])
6813 if (modal_window && viewport->Window && IsWindowAbove(viewport->Window, modal_window))
6815 ImDrawList *draw_list = GetForegroundDrawList(viewport);
6816 const ImU32 dim_bg_col =
6817 GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio);
6818 draw_list->AddRectFilled(viewport->Pos, viewport->Pos + viewport->Size, dim_bg_col);
6824void ImGui::EndFrame()
6827 IM_ASSERT(g.Initialized);
6830 if (g.FrameCountEnded == g.FrameCount)
6832 IM_ASSERT(g.WithinFrameScope &&
"Forgot to call ImGui::NewFrame()?");
6834 CallContextHooks(&g, ImGuiContextHookType_EndFramePre);
6837 if (g.IO.ConfigErrorRecovery)
6838 ErrorRecoveryTryToRecoverState(&g.StackSizesInNewFrame);
6839 ErrorCheckEndFrameSanityChecks();
6840 ErrorCheckEndFrameFinalizeErrorTooltip();
6844 if (g.PlatformIO.Platform_SetImeDataFn != NULL &&
6847 ImGuiViewport *viewport = FindViewportByID(g.PlatformImeViewport);
6848 IMGUI_DEBUG_LOG_IO(
"[io] Calling Platform_SetImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n",
6849 ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y);
6850 if (viewport == NULL)
6851 viewport = GetMainViewport();
6852 g.PlatformIO.Platform_SetImeDataFn(&g, viewport, ime_data);
6856 g.WithinFrameScopeWithImplicitWindow =
false;
6857 if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed)
6858 g.CurrentWindow->Active =
false;
6865 DockContextEndFrame(&g);
6867 SetCurrentViewport(NULL, NULL);
6870 if (g.DragDropActive)
6872 bool is_delivered = g.DragDropPayload.Delivery;
6873 bool is_elapsed = (g.DragDropSourceFrameCount + 1 < g.FrameCount) &&
6874 ((g.DragDropSourceFlags & ImGuiDragDropFlags_PayloadAutoExpire) ||
6875 g.DragDropMouseButton == -1 || !IsMouseDown(g.DragDropMouseButton));
6876 if (is_delivered || is_elapsed)
6885 if (g.DragDropActive && g.DragDropSourceFrameCount + 1 < g.FrameCount &&
6886 !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
6888 g.DragDropWithinSource =
true;
6890 g.DragDropWithinSource =
false;
6894 g.WithinFrameScope =
false;
6895 g.FrameCountEnded = g.FrameCount;
6898 UpdateMouseMovingWindowEndFrame();
6901 UpdateViewportsEndFrame();
6905 g.WindowsTempSortBuffer.resize(0);
6906 g.WindowsTempSortBuffer.reserve(g.Windows.Size);
6909 if (window->Active &&
6910 (window->Flags & ImGuiWindowFlags_ChildWindow))
6912 AddWindowToSortBuffer(&g.WindowsTempSortBuffer, window);
6917 IM_ASSERT(g.Windows.Size == g.WindowsTempSortBuffer.Size);
6918 g.Windows.swap(g.WindowsTempSortBuffer);
6919 g.IO.MetricsActiveWindows = g.WindowsActiveCount;
6922 g.IO.Fonts->Locked =
false;
6925 g.IO.MousePosPrev = g.IO.MousePos;
6926 g.IO.AppFocusLost =
false;
6927 g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f;
6928 g.IO.InputQueueCharacters.resize(0);
6930 CallContextHooks(&g, ImGuiContextHookType_EndFramePost);
6939 IM_ASSERT(g.Initialized);
6941 if (g.FrameCountEnded != g.FrameCount)
6943 if (g.FrameCountRendered == g.FrameCount)
6945 g.FrameCountRendered = g.FrameCount;
6947 g.IO.MetricsRenderWindows = 0;
6948 CallContextHooks(&g, ImGuiContextHookType_RenderPre);
6953 InitViewportDrawData(viewport);
6954 if (viewport->BgFgDrawLists[0] != NULL)
6955 AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0],
6956 GetBackgroundDrawList(viewport));
6960 RenderDimmedBackgrounds();
6964 windows_to_render_top_most[0] =
6965 (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus))
6966 ? g.NavWindowingTarget->RootWindowDockTree
6968 windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingListWindow : NULL);
6971 IM_MSVC_WARNING_SUPPRESS(
6973 if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 &&
6974 window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1])
6975 AddRootWindowToDrawData(window);
6977 for (
int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++)
6978 if (windows_to_render_top_most[n] &&
6979 IsWindowActiveAndVisible(windows_to_render_top_most[n]))
6981 AddRootWindowToDrawData(windows_to_render_top_most[n]);
6984 if (g.IO.MouseDrawCursor && g.MouseCursor != ImGuiMouseCursor_None)
6985 RenderMouseCursor(g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor, IM_COL32_WHITE, IM_COL32_BLACK,
6986 IM_COL32(0, 0, 0, 48));
6989 g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = 0;
6992 FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
6995 if (viewport->BgFgDrawLists[1] != NULL)
6996 AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0],
6997 GetForegroundDrawList(viewport));
7001 ImDrawData *draw_data = &viewport->DrawDataP;
7002 IM_ASSERT(draw_data->CmdLists.Size == draw_data->CmdListsCount);
7003 for (
ImDrawList *draw_list : draw_data->CmdLists)
7004 draw_list->_PopUnusedDrawCmd();
7006 g.IO.MetricsRenderVertices += draw_data->TotalVtxCount;
7007 g.IO.MetricsRenderIndices += draw_data->TotalIdxCount;
7010 CallContextHooks(&g, ImGuiContextHookType_RenderPost);
7015ImVec2 ImGui::CalcTextSize(
const char *text,
const char *text_end,
bool hide_text_after_double_hash,
float wrap_width)
7019 const char *text_display_end;
7020 if (hide_text_after_double_hash)
7021 text_display_end = FindRenderedTextEnd(text, text_end);
7023 text_display_end = text_end;
7026 const float font_size = g.FontSize;
7027 if (text == text_display_end)
7028 return ImVec2(0.0f, font_size);
7029 ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
7036 text_size.x = IM_TRUNC(text_size.x + 0.99999f);
7048void ImGui::FindHoveredWindowEx(
const ImVec2 &pos,
bool find_first_and_in_any_viewport,
7053 ImGuiWindow *hovered_window_under_moving_window = NULL;
7058 if (find_first_and_in_any_viewport ==
false && g.MovingWindow)
7060 backup_moving_window_viewport = g.MovingWindow->Viewport;
7061 g.MovingWindow->Viewport = g.MouseViewport;
7062 if (!(g.MovingWindow->Flags & ImGuiWindowFlags_NoMouseInputs))
7063 hovered_window = g.MovingWindow;
7066 ImVec2 padding_regular = g.Style.TouchExtraPadding;
7067 ImVec2 padding_for_resize =
7068 ImMax(g.Style.TouchExtraPadding,
ImVec2(g.Style.WindowBorderHoverPadding, g.Style.WindowBorderHoverPadding));
7069 for (
int i = g.Windows.Size - 1; i >= 0; i--)
7072 IM_MSVC_WARNING_SUPPRESS(28182);
7073 if (!window->WasActive || window->Hidden)
7075 if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
7077 IM_ASSERT(window->Viewport);
7078 if (window->Viewport != g.MouseViewport)
7082 ImVec2 hit_padding = (window->Flags & (ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize))
7084 : padding_for_resize;
7085 if (!window->OuterRectClipped.ContainsWithPad(pos, hit_padding))
7090 if (window->HitTestHoleSize.x != 0)
7092 ImVec2 hole_pos(window->Pos.x + (
float)window->HitTestHoleOffset.x,
7093 window->Pos.y + (
float)window->HitTestHoleOffset.y);
7094 ImVec2 hole_size((
float)window->HitTestHoleSize.x, (
float)window->HitTestHoleSize.y);
7095 if (
ImRect(hole_pos, hole_pos + hole_size).Contains(pos))
7099 if (find_first_and_in_any_viewport)
7101 hovered_window = window;
7106 if (hovered_window == NULL)
7107 hovered_window = window;
7108 IM_MSVC_WARNING_SUPPRESS(28182);
7109 if (hovered_window_under_moving_window == NULL &&
7110 (!g.MovingWindow || window->RootWindowDockTree != g.MovingWindow->RootWindowDockTree))
7111 hovered_window_under_moving_window = window;
7112 if (hovered_window && hovered_window_under_moving_window)
7117 *out_hovered_window = hovered_window;
7118 if (out_hovered_window_under_moving_window != NULL)
7119 *out_hovered_window_under_moving_window = hovered_window_under_moving_window;
7120 if (find_first_and_in_any_viewport ==
false && g.MovingWindow)
7121 g.MovingWindow->Viewport = backup_moving_window_viewport;
7124bool ImGui::IsItemActive()
7128 return g.ActiveId == g.LastItemData.ID;
7132bool ImGui::IsItemActivated()
7136 if (g.ActiveId == g.LastItemData.ID && g.ActiveIdPreviousFrame != g.LastItemData.ID)
7141bool ImGui::IsItemDeactivated()
7144 if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated)
7145 return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
7146 return (g.DeactivatedItemData.ID == g.LastItemData.ID && g.LastItemData.ID != 0 &&
7147 g.DeactivatedItemData.ElapseFrame >= g.FrameCount);
7150bool ImGui::IsItemDeactivatedAfterEdit()
7153 return IsItemDeactivated() && g.DeactivatedItemData.HasBeenEditedBefore;
7157bool ImGui::IsItemFocused()
7160 if (g.NavId != g.LastItemData.ID || g.NavId == 0)
7167 if (g.LastItemData.ID == window->ID && window->WriteAccessed)
7175bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button)
7177 return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
7180bool ImGui::IsItemToggledOpen()
7183 return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true :
false;
7191bool ImGui::IsItemToggledSelection()
7194 IM_ASSERT(g.CurrentMultiSelect != NULL);
7195 return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true :
false;
7201bool ImGui::IsAnyItemHovered()
7204 return g.HoveredId != 0 || g.HoveredIdPreviousFrame != 0;
7207bool ImGui::IsAnyItemActive()
7210 return g.ActiveId != 0;
7213bool ImGui::IsAnyItemFocused()
7216 return g.NavId != 0 && g.NavCursorVisible;
7219bool ImGui::IsItemVisible()
7222 return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) != 0;
7225bool ImGui::IsItemEdited()
7228 return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Edited) != 0;
7234void ImGui::SetNextItemAllowOverlap()
7237 g.NextItemData.ItemFlags |= ImGuiItemFlags_AllowOverlap;
7240#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
7244void ImGui::SetItemAllowOverlap()
7247 ImGuiID
id = g.LastItemData.ID;
7248 if (g.HoveredId ==
id)
7249 g.HoveredIdAllowOverlap =
true;
7250 if (g.ActiveId ==
id)
7252 g.ActiveIdAllowOverlap =
true;
7259void ImGui::SetActiveIdUsingAllKeyboardKeys()
7262 IM_ASSERT(g.ActiveId != 0);
7263 g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_COUNT) - 1;
7264 g.ActiveIdUsingAllKeyboardKeys =
true;
7265 NavMoveRequestCancel();
7268ImGuiID ImGui::GetItemID()
7271 return g.LastItemData.ID;
7274ImVec2 ImGui::GetItemRectMin()
7277 return g.LastItemData.Rect.Min;
7280ImVec2 ImGui::GetItemRectMax()
7283 return g.LastItemData.Rect.Max;
7286ImVec2 ImGui::GetItemRectSize()
7289 return g.LastItemData.Rect.GetSize();
7295bool ImGui::BeginChild(
const char *str_id,
const ImVec2 &size_arg, ImGuiChildFlags child_flags,
7296 ImGuiWindowFlags window_flags)
7298 ImGuiID
id = GetCurrentWindow()->GetID(str_id);
7299 return BeginChildEx(str_id,
id, size_arg, child_flags, window_flags);
7302bool ImGui::BeginChild(ImGuiID
id,
const ImVec2 &size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags)
7304 return BeginChildEx(NULL,
id, size_arg, child_flags, window_flags);
7307bool ImGui::BeginChildEx(
const char *name, ImGuiID
id,
const ImVec2 &size_arg, ImGuiChildFlags child_flags,
7308 ImGuiWindowFlags window_flags)
7316 const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ =
7317 ImGuiChildFlags_Borders | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_ResizeX |
7318 ImGuiChildFlags_ResizeY | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY |
7319 ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_FrameStyle | ImGuiChildFlags_NavFlattened;
7320 IM_UNUSED(ImGuiChildFlags_SupportedMask_);
7321 IM_ASSERT((child_flags & ~ImGuiChildFlags_SupportedMask_) == 0 &&
7322 "Illegal ImGuiChildFlags value. Did you pass ImGuiWindowFlags values instead of ImGuiChildFlags?");
7324 (window_flags & ImGuiWindowFlags_AlwaysAutoResize) == 0 &&
7325 "Cannot specify ImGuiWindowFlags_AlwaysAutoResize for BeginChild(). Use ImGuiChildFlags_AlwaysAutoResize!");
7326 if (child_flags & ImGuiChildFlags_AlwaysAutoResize)
7329 (child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0 &&
7330 "Cannot use ImGuiChildFlags_ResizeX or ImGuiChildFlags_ResizeY with ImGuiChildFlags_AlwaysAutoResize!");
7331 IM_ASSERT((child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY)) != 0 &&
7332 "Must use ImGuiChildFlags_AutoResizeX or ImGuiChildFlags_AutoResizeY with "
7333 "ImGuiChildFlags_AlwaysAutoResize!");
7335#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
7336 if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding)
7337 child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding;
7338 if (window_flags & ImGuiWindowFlags_NavFlattened)
7339 child_flags |= ImGuiChildFlags_NavFlattened;
7341 if (child_flags & ImGuiChildFlags_AutoResizeX)
7342 child_flags &= ~ImGuiChildFlags_ResizeX;
7343 if (child_flags & ImGuiChildFlags_AutoResizeY)
7344 child_flags &= ~ImGuiChildFlags_ResizeY;
7347 window_flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking;
7348 window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove);
7349 if (child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize))
7350 window_flags |= ImGuiWindowFlags_AlwaysAutoResize;
7351 if ((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0)
7352 window_flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
7355 if (child_flags & ImGuiChildFlags_FrameStyle)
7357 PushStyleColor(ImGuiCol_ChildBg, g.Style.Colors[ImGuiCol_FrameBg]);
7358 PushStyleVar(ImGuiStyleVar_ChildRounding, g.Style.FrameRounding);
7359 PushStyleVar(ImGuiStyleVar_ChildBorderSize, g.Style.FrameBorderSize);
7360 PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.FramePadding);
7361 child_flags |= ImGuiChildFlags_Borders | ImGuiChildFlags_AlwaysUseWindowPadding;
7362 window_flags |= ImGuiWindowFlags_NoMove;
7369 const ImVec2 size_avail = GetContentRegionAvail();
7370 const ImVec2 size_default((child_flags & ImGuiChildFlags_AutoResizeX) ? 0.0f : size_avail.x,
7371 (child_flags & ImGuiChildFlags_AutoResizeY) ? 0.0f : size_avail.y);
7372 ImVec2 size = CalcItemSize(size_arg, size_default.x, size_default.y);
7379 if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) != 0 &&
7380 (g.NextWindowData.SizeCond & ImGuiCond_Always) != 0)
7382 if (g.NextWindowData.SizeVal.x > 0.0f)
7384 size.x = g.NextWindowData.SizeVal.x;
7385 child_flags &= ~ImGuiChildFlags_ResizeX;
7387 if (g.NextWindowData.SizeVal.y > 0.0f)
7389 size.y = g.NextWindowData.SizeVal.y;
7390 child_flags &= ~ImGuiChildFlags_ResizeY;
7393 SetNextWindowSize(size);
7396 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags)
7397 g.NextWindowData.ChildFlags |= child_flags;
7399 g.NextWindowData.ChildFlags = child_flags;
7400 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags;
7407 const char *temp_window_name;
7412 ImFormatStringToTempBuffer(&temp_window_name, NULL,
"%s/%s_%08X", parent_window->Name, name,
id);
7414 ImFormatStringToTempBuffer(&temp_window_name, NULL,
"%s/%08X", parent_window->Name,
id);
7417 const float backup_border_size = g.Style.ChildBorderSize;
7418 if ((child_flags & ImGuiChildFlags_Borders) == 0)
7419 g.Style.ChildBorderSize = 0.0f;
7422 const bool ret = Begin(temp_window_name, NULL, window_flags);
7425 g.Style.ChildBorderSize = backup_border_size;
7426 if (child_flags & ImGuiChildFlags_FrameStyle)
7433 child_window->ChildId = id;
7437 if (child_window->BeginCount == 1)
7438 parent_window->DC.CursorPos = child_window->Pos;
7442 const ImGuiID temp_id_for_activation = ImHashStr(
"##Child", 0,
id);
7443 if (g.ActiveId == temp_id_for_activation)
7445 if (g.NavActivateId ==
id && !(child_flags & ImGuiChildFlags_NavFlattened) &&
7446 (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY))
7448 FocusWindow(child_window);
7449 NavInitWindow(child_window,
false);
7451 temp_id_for_activation,
7453 g.ActiveIdSource = g.NavInputSource;
7458void ImGui::EndChild()
7463 const ImGuiID backup_within_end_child_id = g.WithinEndChildID;
7464 IM_ASSERT(child_window->Flags & ImGuiWindowFlags_ChildWindow);
7466 g.WithinEndChildID = child_window->ID;
7467 ImVec2 child_size = child_window->Size;
7469 if (child_window->BeginCount == 1)
7472 ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + child_size);
7473 ItemSize(child_size);
7474 const bool nav_flattened = (child_window->ChildFlags & ImGuiChildFlags_NavFlattened) != 0;
7475 if ((child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY) && !nav_flattened)
7477 ItemAdd(bb, child_window->ChildId);
7478 RenderNavCursor(bb, child_window->ChildId);
7482 if (child_window->DC.NavLayersActiveMask == 0 && child_window == g.NavWindow)
7484 ImGuiNavRenderCursorFlags_Compact);
7493 ItemAdd(bb, child_window->ChildId, NULL, ImGuiItemFlags_NoNav);
7497 parent_window->DC.NavLayersActiveMaskNext |= child_window->DC.NavLayersActiveMaskNext;
7499 if (g.HoveredWindow == child_window)
7500 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
7501 child_window->DC.ChildItemStatusFlags = g.LastItemData.StatusFlags;
7507 SetLastItemDataForChildWindowItem(child_window, child_window->Rect());
7510 g.WithinEndChildID = backup_within_end_child_id;
7511 g.LogLinePosY = -FLT_MAX;
7514static void SetWindowConditionAllowFlags(
ImGuiWindow *window, ImGuiCond flags,
bool enabled)
7516 window->SetWindowPosAllowFlags =
7517 enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
7518 window->SetWindowSizeAllowFlags =
7519 enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags);
7520 window->SetWindowCollapsedAllowFlags =
7521 enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags);
7522 window->SetWindowDockAllowFlags =
7523 enabled ? (window->SetWindowDockAllowFlags | flags) : (window->SetWindowDockAllowFlags & ~flags);
7529 return (
ImGuiWindow *)g.WindowsById.GetVoidPtr(
id);
7532ImGuiWindow *ImGui::FindWindowByName(
const char *name)
7534 ImGuiID
id = ImHashStr(name);
7535 return FindWindowByID(
id);
7540 const ImGuiViewport *main_viewport = ImGui::GetMainViewport();
7541 window->ViewportPos = main_viewport->Pos;
7542 if (settings->ViewportId)
7544 window->ViewportId = settings->ViewportId;
7545 window->ViewportPos =
ImVec2(settings->ViewportPos.x, settings->ViewportPos.y);
7547 window->Pos = ImTrunc(
ImVec2(settings->Pos.x + window->ViewportPos.x, settings->Pos.y + window->ViewportPos.y));
7548 if (settings->Size.x > 0 && settings->Size.y > 0)
7549 window->Size = window->SizeFull = ImTrunc(
ImVec2(settings->Size.x, settings->Size.y));
7550 window->Collapsed = settings->Collapsed;
7551 window->DockId = settings->DockId;
7552 window->DockOrder = settings->DockOrder;
7559 const ImGuiViewport *main_viewport = ImGui::GetMainViewport();
7560 window->Pos = main_viewport->Pos +
ImVec2(60, 60);
7561 window->Size = window->SizeFull =
ImVec2(0, 0);
7562 window->ViewportPos = main_viewport->Pos;
7563 window->SetWindowPosAllowFlags = window->SetWindowSizeAllowFlags = window->SetWindowCollapsedAllowFlags =
7564 window->SetWindowDockAllowFlags =
7565 ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
7567 if (settings != NULL)
7569 SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver,
false);
7570 ApplyWindowSettings(window, settings);
7572 window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos =
7575 if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
7577 window->AutoFitFramesX = window->AutoFitFramesY = 2;
7578 window->AutoFitOnlyGrows =
false;
7582 if (window->Size.x <= 0.0f)
7583 window->AutoFitFramesX = 2;
7584 if (window->Size.y <= 0.0f)
7585 window->AutoFitFramesY = 2;
7586 window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
7590static ImGuiWindow *CreateNewWindow(
const char *name, ImGuiWindowFlags flags)
7596 window->Flags = flags;
7597 g.WindowsById.SetVoidPtr(window->ID, window);
7600 if (!(flags & ImGuiWindowFlags_NoSavedSettings))
7601 if ((settings = ImGui::FindWindowSettingsByWindow(window)) != 0)
7602 window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings);
7604 InitOrLoadWindowSettings(window, settings);
7606 if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)
7607 g.Windows.push_front(window);
7609 g.Windows.push_back(window);
7616 return window->DockNodeAsHost ? window->DockNodeAsHost->VisibleWindow : window;
7621 return (window->DockNodeAsHost && window->DockNodeAsHost->VisibleWindow) ? window->DockNodeAsHost->VisibleWindow
7632 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Popup))
7634 size_min.x = (window->ChildFlags & ImGuiChildFlags_ResizeX) ? g.Style.WindowMinSize.x : 4.0f;
7635 size_min.y = (window->ChildFlags & ImGuiChildFlags_ResizeY) ? g.Style.WindowMinSize.y : 4.0f;
7639 size_min.x = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ? g.Style.WindowMinSize.x : 4.0f;
7640 size_min.y = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ? g.Style.WindowMinSize.y : 4.0f;
7644 ImGuiWindow *window_for_height = GetWindowForTitleAndMenuHeight(window);
7645 size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight + window_for_height->MenuBarHeight +
7646 ImMax(0.0f, g.Style.WindowRounding - 1.0f));
7653 ImVec2 new_size = size_desired;
7654 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSizeConstraint)
7657 ImRect cr = g.NextWindowData.SizeConstraintRect;
7658 new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
7659 new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;
7660 if (g.NextWindowData.SizeCallback)
7663 data.UserData = g.NextWindowData.SizeCallbackUserData;
7664 data.Pos = window->Pos;
7665 data.CurrentSize = window->SizeFull;
7666 data.DesiredSize = new_size;
7667 g.NextWindowData.SizeCallback(&data);
7668 new_size = data.DesiredSize;
7670 new_size.x = IM_TRUNC(new_size.x);
7671 new_size.y = IM_TRUNC(new_size.y);
7675 ImVec2 size_min = CalcWindowMinSize(window);
7676 return ImMax(new_size, size_min);
7679static void CalcWindowContentSizes(
ImGuiWindow *window,
ImVec2 *content_size_current,
ImVec2 *content_size_ideal)
7681 bool preserve_old_content_sizes =
false;
7682 if (window->Collapsed && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
7683 preserve_old_content_sizes =
true;
7684 else if (window->Hidden && window->HiddenFramesCannotSkipItems == 0 && window->HiddenFramesCanSkipItems > 0)
7685 preserve_old_content_sizes =
true;
7686 if (preserve_old_content_sizes)
7688 *content_size_current = window->ContentSize;
7689 *content_size_ideal = window->ContentSizeIdeal;
7693 content_size_current->x = (window->ContentSizeExplicit.x != 0.0f)
7694 ? window->ContentSizeExplicit.x
7695 : IM_TRUNC(window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x);
7696 content_size_current->y = (window->ContentSizeExplicit.y != 0.0f)
7697 ? window->ContentSizeExplicit.y
7698 : IM_TRUNC(window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y);
7699 content_size_ideal->x =
7700 (window->ContentSizeExplicit.x != 0.0f)
7701 ? window->ContentSizeExplicit.x
7702 : IM_TRUNC(ImMax(window->DC.CursorMaxPos.x, window->DC.IdealMaxPos.x) - window->DC.CursorStartPos.x);
7703 content_size_ideal->y =
7704 (window->ContentSizeExplicit.y != 0.0f)
7705 ? window->ContentSizeExplicit.y
7706 : IM_TRUNC(ImMax(window->DC.CursorMaxPos.y, window->DC.IdealMaxPos.y) - window->DC.CursorStartPos.y);
7713 const float decoration_w_without_scrollbars =
7714 window->DecoOuterSizeX1 + window->DecoOuterSizeX2 - window->ScrollbarSizes.x;
7715 const float decoration_h_without_scrollbars =
7716 window->DecoOuterSizeY1 + window->DecoOuterSizeY2 - window->ScrollbarSizes.y;
7717 ImVec2 size_pad = window->WindowPadding * 2.0f;
7719 size_contents + size_pad +
ImVec2(decoration_w_without_scrollbars, decoration_h_without_scrollbars);
7720 if (window->Flags & ImGuiWindowFlags_Tooltip)
7723 return size_desired;
7728 ImVec2 size_min = CalcWindowMinSize(window);
7732 if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || (window->Flags & ImGuiWindowFlags_Popup) != 0)
7734 if (!window->ViewportOwned)
7735 size_max = ImGui::GetMainViewport()->WorkSize - style.DisplaySafeAreaPadding * 2.0f;
7736 const int monitor_idx = window->ViewportAllowPlatformMonitorExtend;
7737 if (monitor_idx >= 0 && monitor_idx < g.PlatformIO.Monitors.Size)
7738 size_max = g.PlatformIO.Monitors[monitor_idx].WorkSize - style.DisplaySafeAreaPadding * 2.0f;
7741 ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, size_max));
7746 if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && !(window->ChildFlags & ImGuiChildFlags_ResizeY))
7747 size_auto_fit.y = window->SizeFull.y;
7748 else if (!(window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->ChildFlags & ImGuiChildFlags_ResizeY))
7749 size_auto_fit.x = window->SizeFull.x;
7754 ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit);
7755 bool will_have_scrollbar_x =
7756 (size_auto_fit_after_constraint.x - size_pad.x - decoration_w_without_scrollbars < size_contents.x &&
7757 !(window->Flags & ImGuiWindowFlags_NoScrollbar) &&
7758 (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) ||
7759 (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar);
7760 bool will_have_scrollbar_y =
7761 (size_auto_fit_after_constraint.y - size_pad.y - decoration_h_without_scrollbars < size_contents.y &&
7762 !(window->Flags & ImGuiWindowFlags_NoScrollbar)) ||
7763 (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar);
7764 if (will_have_scrollbar_x)
7765 size_auto_fit.y += style.ScrollbarSize;
7766 if (will_have_scrollbar_y)
7767 size_auto_fit.x += style.ScrollbarSize;
7768 return size_auto_fit;
7774 ImVec2 size_contents_current;
7775 ImVec2 size_contents_ideal;
7776 CalcWindowContentSizes(window, &size_contents_current, &size_contents_ideal);
7777 ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, size_contents_ideal);
7778 ImVec2 size_final = CalcWindowSizeAfterConstraint(window, size_auto_fit);
7782static ImGuiCol GetWindowBgColorIdx(
ImGuiWindow *window)
7784 if (window->Flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
7785 return ImGuiCol_PopupBg;
7786 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !window->DockIsActive)
7787 return ImGuiCol_ChildBg;
7788 return ImGuiCol_WindowBg;
7791static void CalcResizePosSizeFromAnyCorner(
ImGuiWindow *window,
const ImVec2 &corner_target,
const ImVec2 &corner_norm,
7794 ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm);
7795 ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm);
7796 ImVec2 size_expected = pos_max - pos_min;
7797 ImVec2 size_constrained = CalcWindowSizeAfterConstraint(window, size_expected);
7799 if (corner_norm.x == 0.0f)
7800 out_pos->x -= (size_constrained.x - size_expected.x);
7801 if (corner_norm.y == 0.0f)
7802 out_pos->y -= (size_constrained.y - size_expected.y);
7803 *out_size = size_constrained;
7811 int AngleMin12, AngleMax12;
7824 ImVec2 SegmentN1, SegmentN2;
7834static ImRect GetResizeBorderRect(
ImGuiWindow *window,
int border_n,
float perp_padding,
float thickness)
7836 ImRect rect = window->Rect();
7837 if (thickness == 0.0f)
7838 rect.Max -=
ImVec2(1, 1);
7839 if (border_n == ImGuiDir_Left)
7841 return ImRect(rect.Min.x - thickness, rect.Min.y + perp_padding, rect.Min.x + thickness,
7842 rect.Max.y - perp_padding);
7844 if (border_n == ImGuiDir_Right)
7846 return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x + thickness,
7847 rect.Max.y - perp_padding);
7849 if (border_n == ImGuiDir_Up)
7851 return ImRect(rect.Min.x + perp_padding, rect.Min.y - thickness, rect.Max.x - perp_padding,
7852 rect.Min.y + thickness);
7854 if (border_n == ImGuiDir_Down)
7856 return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding,
7857 rect.Max.y + thickness);
7864ImGuiID ImGui::GetWindowResizeCornerID(
ImGuiWindow *window,
int n)
7866 IM_ASSERT(n >= 0 && n < 4);
7867 ImGuiID
id = window->DockIsActive ? window->DockNode->HostWindow->ID : window->ID;
7868 id = ImHashStr(
"#RESIZE", 0,
id);
7869 id = ImHashData(&n,
sizeof(
int),
id);
7874ImGuiID ImGui::GetWindowResizeBorderID(
ImGuiWindow *window, ImGuiDir dir)
7876 IM_ASSERT(dir >= 0 && dir < 4);
7877 int n = (int)dir + 4;
7878 ImGuiID
id = window->DockIsActive ? window->DockNode->HostWindow->ID : window->ID;
7879 id = ImHashStr(
"#RESIZE", 0,
id);
7880 id = ImHashData(&n,
sizeof(
int),
id);
7886static int ImGui::UpdateWindowManualResize(
ImGuiWindow *window,
const ImVec2 &size_auto_fit,
int *border_hovered,
7887 int *border_held,
int resize_grip_count, ImU32 resize_grip_col[4],
7888 const ImRect &visibility_rect)
7891 ImGuiWindowFlags flags = window->Flags;
7893 if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) ||
7894 window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
7896 if (window->WasActive ==
7900 int ret_auto_fit_mask = 0x00;
7901 const float grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
7902 const float grip_hover_inner_size = (resize_grip_count > 0) ? IM_TRUNC(grip_draw_size * 0.75f) : 0.0f;
7903 const float grip_hover_outer_size = g.WindowsBorderHoverPadding;
7905 ImRect clamp_rect = visibility_rect;
7906 const bool window_move_from_title_bar =
7907 g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar);
7908 if (window_move_from_title_bar)
7909 clamp_rect.Min.y -= window->TitleBarHeight;
7911 ImVec2 pos_target(FLT_MAX, FLT_MAX);
7912 ImVec2 size_target(FLT_MAX, FLT_MAX);
7925 const bool clip_with_viewport_rect = !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport) ||
7926 (g.IO.MouseHoveredViewport != window->ViewportId) ||
7927 !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration);
7928 if (clip_with_viewport_rect)
7929 window->ClipRect = window->Viewport->GetMainRect();
7932 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
7936 for (
int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
7939 const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, def.CornerPosN);
7944 ImRect resize_rect(corner - def.InnerDir * grip_hover_outer_size,
7945 corner + def.InnerDir * grip_hover_inner_size);
7946 if (resize_rect.Min.x > resize_rect.Max.x)
7947 ImSwap(resize_rect.Min.x, resize_rect.Max.x);
7948 if (resize_rect.Min.y > resize_rect.Max.y)
7949 ImSwap(resize_rect.Min.y, resize_rect.Max.y);
7950 ImGuiID resize_grip_id = window->GetID(resize_grip_n);
7951 ItemAdd(resize_rect, resize_grip_id, NULL, ImGuiItemFlags_NoNav);
7952 ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held,
7953 ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
7955 if (hovered || held)
7956 SetMouseCursor((resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE);
7958 if (held && g.IO.MouseDoubleClicked[0])
7961 size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit);
7962 ret_auto_fit_mask = 0x03;
7970 ImVec2(def.CornerPosN.x == 1.0f ? clamp_rect.Min.x : -FLT_MAX,
7971 (def.CornerPosN.y == 1.0f || (def.CornerPosN.y == 0.0f && window_move_from_title_bar))
7974 ImVec2 clamp_max =
ImVec2(def.CornerPosN.x == 0.0f ? clamp_rect.Max.x : +FLT_MAX,
7975 def.CornerPosN.y == 0.0f ? clamp_rect.Max.y : +FLT_MAX);
7976 ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset +
7977 ImLerp(def.InnerDir * grip_hover_outer_size, def.InnerDir * -grip_hover_inner_size,
7979 corner_target = ImClamp(corner_target, clamp_min, clamp_max);
7980 CalcResizePosSizeFromAnyCorner(window, corner_target, def.CornerPosN, &pos_target, &size_target);
7984 if (resize_grip_n == 0 || held || hovered)
7985 resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive
7986 : hovered ? ImGuiCol_ResizeGripHovered
7987 : ImGuiCol_ResizeGrip);
7990 int resize_border_mask = 0x00;
7991 if (window->Flags & ImGuiWindowFlags_ChildWindow)
7992 resize_border_mask |= ((window->ChildFlags & ImGuiChildFlags_ResizeX) ? 0x02 : 0) |
7993 ((window->ChildFlags & ImGuiChildFlags_ResizeY) ? 0x08 : 0);
7995 resize_border_mask = g.IO.ConfigWindowsResizeFromEdges ? 0x0F : 0x00;
7996 for (
int border_n = 0; border_n < 4; border_n++)
7998 if ((resize_border_mask & (1 << border_n)) == 0)
8001 const ImGuiAxis axis = (border_n == ImGuiDir_Left || border_n == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
8004 ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, g.WindowsBorderHoverPadding);
8005 ImGuiID border_id = window->GetID(border_n + 4);
8006 ItemAdd(border_rect, border_id, NULL, ImGuiItemFlags_NoNav);
8007 ButtonBehavior(border_rect, border_id, &hovered, &held,
8008 ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
8010 if (hovered && g.HoveredIdTimer <= WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER)
8012 if (hovered || held)
8013 SetMouseCursor((axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS);
8014 if (held && g.IO.MouseDoubleClicked[0])
8021 if (border_n == 1 || border_n == 3)
8023 size_target[axis] = CalcWindowSizeAfterConstraint(window, size_auto_fit)[axis];
8024 ret_auto_fit_mask |= (1 << axis);
8025 hovered = held =
false;
8036 const bool just_scrolled_manually_while_resizing =
8037 (g.WheelingWindow != NULL && g.WheelingWindowScrolledFrame == g.FrameCount &&
8038 IsWindowChildOf(window, g.WheelingWindow,
false,
true));
8039 if (g.ActiveIdIsJustActivated || just_scrolled_manually_while_resizing)
8041 g.WindowResizeBorderExpectedRect = border_rect;
8042 g.WindowResizeRelativeMode =
false;
8044 if ((window->Flags & ImGuiWindowFlags_ChildWindow) &&
8045 memcmp(&g.WindowResizeBorderExpectedRect, &border_rect,
sizeof(
ImRect)) != 0)
8046 g.WindowResizeRelativeMode =
true;
8048 const ImVec2 border_curr = (window->Pos + ImMin(def.SegmentN1, def.SegmentN2) * window->Size);
8049 const float border_target_rel_mode_for_axis = border_curr[axis] + g.IO.MouseDelta[axis];
8050 const float border_target_abs_mode_for_axis =
8051 g.IO.MousePos[axis] - g.ActiveIdClickOffset[axis] +
8052 g.WindowsBorderHoverPadding;
8055 ImVec2 border_target = window->Pos;
8056 border_target[axis] = border_target_abs_mode_for_axis;
8060 bool ignore_resize =
false;
8061 if (g.WindowResizeRelativeMode)
8064 border_target[axis] = border_target_rel_mode_for_axis;
8065 if (g.IO.MouseDelta[axis] == 0.0f ||
8066 (g.IO.MouseDelta[axis] > 0.0f) ==
8067 (border_target_rel_mode_for_axis > border_target_abs_mode_for_axis))
8068 ignore_resize =
true;
8072 ImVec2 clamp_min(border_n == ImGuiDir_Right ? clamp_rect.Min.x : -FLT_MAX,
8073 border_n == ImGuiDir_Down || (border_n == ImGuiDir_Up && window_move_from_title_bar)
8076 ImVec2 clamp_max(border_n == ImGuiDir_Left ? clamp_rect.Max.x : +FLT_MAX,
8077 border_n == ImGuiDir_Up ? clamp_rect.Max.y : +FLT_MAX);
8078 border_target = ImClamp(border_target, clamp_min, clamp_max);
8079 if (flags & ImGuiWindowFlags_ChildWindow)
8081 ImGuiWindow *parent_window = window->ParentWindow;
8082 ImGuiWindowFlags parent_flags = parent_window->Flags;
8083 ImRect border_limit_rect = parent_window->InnerRect;
8084 border_limit_rect.Expand(
8085 ImVec2(-ImMax(parent_window->WindowPadding.x, parent_window->WindowBorderSize),
8086 -ImMax(parent_window->WindowPadding.y, parent_window->WindowBorderSize)));
8087 if ((axis == ImGuiAxis_X) && ((parent_flags & (ImGuiWindowFlags_HorizontalScrollbar |
8088 ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 ||
8089 (parent_flags & ImGuiWindowFlags_NoScrollbar)))
8090 border_target.x = ImClamp(border_target.x, border_limit_rect.Min.x, border_limit_rect.Max.x);
8091 if ((axis == ImGuiAxis_Y) && (parent_flags & ImGuiWindowFlags_NoScrollbar))
8092 border_target.y = ImClamp(border_target.y, border_limit_rect.Min.y, border_limit_rect.Max.y);
8095 CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.SegmentN1, def.SegmentN2), &pos_target,
8099 *border_hovered = border_n;
8101 *border_held = border_n;
8106 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
8111 if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindowDockTree == window)
8114 if (g.NavInputSource == ImGuiInputSource_Keyboard && g.IO.KeyShift)
8116 GetKeyMagnitude2d(ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow);
8117 if (g.NavInputSource == ImGuiInputSource_Gamepad)
8118 nav_resize_dir = GetKeyMagnitude2d(ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadRight,
8119 ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown);
8120 if (nav_resize_dir.x != 0.0f || nav_resize_dir.y != 0.0f)
8122 const float NAV_RESIZE_SPEED = 600.0f;
8123 const float resize_step = NAV_RESIZE_SPEED * g.IO.DeltaTime *
8124 ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y);
8125 g.NavWindowingAccumDeltaSize += nav_resize_dir * resize_step;
8126 g.NavWindowingAccumDeltaSize =
8127 ImMax(g.NavWindowingAccumDeltaSize,
8128 clamp_rect.Min - window->Pos -
8131 g.NavWindowingToggleLayer =
false;
8132 g.NavHighlightItemUnderNav =
true;
8133 resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
8134 ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaSize);
8135 if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
8139 size_target = CalcWindowSizeAfterConstraint(window, window->SizeFull + accum_floored);
8140 g.NavWindowingAccumDeltaSize -= accum_floored;
8146 const ImVec2 curr_pos = window->Pos;
8147 const ImVec2 curr_size = window->SizeFull;
8148 if (size_target.x != FLT_MAX && (window->Size.x != size_target.x || window->SizeFull.x != size_target.x))
8149 window->Size.x = window->SizeFull.x = size_target.x;
8150 if (size_target.y != FLT_MAX && (window->Size.y != size_target.y || window->SizeFull.y != size_target.y))
8151 window->Size.y = window->SizeFull.y = size_target.y;
8152 if (pos_target.x != FLT_MAX && window->Pos.x != ImTrunc(pos_target.x))
8153 window->Pos.x = ImTrunc(pos_target.x);
8154 if (pos_target.y != FLT_MAX && window->Pos.y != ImTrunc(pos_target.y))
8155 window->Pos.y = ImTrunc(pos_target.y);
8156 if (curr_pos.x != window->Pos.x || curr_pos.y != window->Pos.y || curr_size.x != window->SizeFull.x ||
8157 curr_size.y != window->SizeFull.y)
8158 MarkIniSettingsDirty(window);
8161 if (*border_held != -1)
8162 g.WindowResizeBorderExpectedRect =
8163 GetResizeBorderRect(window, *border_held, grip_hover_inner_size, g.WindowsBorderHoverPadding);
8165 return ret_auto_fit_mask;
8168static inline void ClampWindowPos(
ImGuiWindow *window,
const ImRect &visibility_rect)
8171 ImVec2 size_for_clamping = window->Size;
8172 if (g.IO.ConfigWindowsMoveFromTitleBarOnly && window->DockNodeAsHost)
8173 size_for_clamping.y =
8174 ImGui::GetFrameHeight();
8175 else if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
8176 size_for_clamping.y = window->TitleBarHeight;
8177 window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
8180static void RenderWindowOuterSingleBorder(
ImGuiWindow *window,
int border_n, ImU32 border_col,
float border_size)
8183 const float rounding = window->WindowRounding;
8184 const ImRect border_r = GetResizeBorderRect(window, border_n, rounding, 0.0f);
8185 window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN1) +
ImVec2(0.5f, 0.5f) +
8186 def.InnerDir * rounding,
8187 rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle);
8188 window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN2) +
ImVec2(0.5f, 0.5f) +
8189 def.InnerDir * rounding,
8190 rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f);
8191 window->DrawList->PathStroke(border_col, ImDrawFlags_None, border_size);
8194static void ImGui::RenderWindowOuterBorders(
ImGuiWindow *window)
8197 const float border_size = window->WindowBorderSize;
8198 const ImU32 border_col = GetColorU32(ImGuiCol_Border);
8199 if (border_size > 0.0f && (window->Flags & ImGuiWindowFlags_NoBackground) == 0)
8200 window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, 0,
8201 window->WindowBorderSize);
8202 else if (border_size > 0.0f)
8204 if (window->ChildFlags &
8205 ImGuiChildFlags_ResizeX)
8207 RenderWindowOuterSingleBorder(window, 1, border_col, border_size);
8208 if (window->ChildFlags & ImGuiChildFlags_ResizeY)
8209 RenderWindowOuterSingleBorder(window, 3, border_col, border_size);
8211 if (window->ResizeBorderHovered != -1 || window->ResizeBorderHeld != -1)
8213 const int border_n = (window->ResizeBorderHeld != -1) ? window->ResizeBorderHeld : window->ResizeBorderHovered;
8214 const ImU32 border_col_resizing =
8215 GetColorU32((window->ResizeBorderHeld != -1) ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered);
8216 RenderWindowOuterSingleBorder(window, border_n, border_col_resizing,
8217 ImMax(2.0f, window->WindowBorderSize));
8219 if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
8221 float y = window->Pos.y + window->TitleBarHeight - 1;
8222 window->DrawList->AddLine(
ImVec2(window->Pos.x + border_size * 0.5f, y),
8223 ImVec2(window->Pos.x + window->Size.x - border_size * 0.5f, y), border_col,
8224 g.Style.FrameBorderSize);
8230void ImGui::RenderWindowDecorations(
ImGuiWindow *window,
const ImRect &title_bar_rect,
bool title_bar_is_highlight,
8231 bool handle_borders_and_resize_grips,
int resize_grip_count,
8232 const ImU32 resize_grip_col[4],
float resize_grip_draw_size)
8236 ImGuiWindowFlags flags = window->Flags;
8239 IM_ASSERT(window->BeginCount == 0);
8240 window->SkipItems =
false;
8241 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
8246 const float window_rounding = window->WindowRounding;
8247 const float window_border_size = window->WindowBorderSize;
8248 if (window->Collapsed)
8251 const float backup_border_size = style.FrameBorderSize;
8252 g.Style.FrameBorderSize = window->WindowBorderSize;
8253 ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && g.NavCursorVisible) ? ImGuiCol_TitleBgActive
8254 : ImGuiCol_TitleBgCollapsed);
8255 if (window->ViewportOwned)
8259 RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col,
true, window_rounding);
8260 g.Style.FrameBorderSize = backup_border_size;
8265 if (!(flags & ImGuiWindowFlags_NoBackground))
8267 bool is_docking_transparent_payload =
false;
8268 if (g.DragDropActive && (g.FrameCount - g.DragDropAcceptFrameCount) <= 1 &&
8269 g.IO.ConfigDockingTransparentPayload)
8270 if (g.DragDropPayload.IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) &&
8271 *(
ImGuiWindow **)g.DragDropPayload.Data == window)
8272 is_docking_transparent_payload =
true;
8274 ImU32 bg_col = GetColorU32(GetWindowBgColorIdx(window));
8275 if (window->ViewportOwned)
8277 bg_col |= IM_COL32_A_MASK;
8278 if (is_docking_transparent_payload)
8279 window->Viewport->Alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
8284 bool override_alpha =
false;
8286 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasBgAlpha)
8288 alpha = g.NextWindowData.BgAlphaVal;
8289 override_alpha =
true;
8291 if (is_docking_transparent_payload)
8293 alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
8294 override_alpha =
true;
8297 bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
8301 if (window->DockIsActive)
8302 window->DockNode->LastBgColor = bg_col;
8303 ImDrawList *bg_draw_list = window->DockIsActive ? window->DockNode->HostWindow->DrawList : window->DrawList;
8304 if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
8305 bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
8306 bg_draw_list->AddRectFilled(window->Pos +
ImVec2(0, window->TitleBarHeight), window->Pos + window->Size,
8307 bg_col, window_rounding,
8308 (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
8309 if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
8310 bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
8312 if (window->DockIsActive)
8313 window->DockNode->IsBgDrawnThisFrame =
true;
8318 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
8320 ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
8321 if (window->ViewportOwned)
8322 title_bar_col |= IM_COL32_A_MASK;
8323 window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding,
8324 ImDrawFlags_RoundCornersTop);
8328 if (flags & ImGuiWindowFlags_MenuBar)
8330 ImRect menu_bar_rect = window->MenuBarRect();
8331 menu_bar_rect.ClipWith(window->Rect());
8333 window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg),
8334 (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f,
8335 ImDrawFlags_RoundCornersTop);
8336 if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
8337 window->DrawList->AddLine(menu_bar_rect.GetBL() +
ImVec2(window_border_size * 0.5f, 0.0f),
8338 menu_bar_rect.GetBR() -
ImVec2(window_border_size * 0.5f, 0.0f),
8339 GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
8344 if (window->DockIsActive && node->IsHiddenTabBar() && !node->IsNoTabBar())
8346 float unhide_sz_draw = ImTrunc(g.FontSize * 0.70f);
8347 float unhide_sz_hit = ImTrunc(g.FontSize * 0.55f);
8350 ImGuiID unhide_id = window->GetID(
"#UNHIDE");
8351 KeepAliveID(unhide_id);
8353 if (ButtonBehavior(r, unhide_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren))
8354 node->WantHiddenTabBarToggle =
true;
8355 else if (held && IsMouseDragging(0))
8356 StartMouseMovingWindowOrNode(
8357 window, node,
true);
8361 ImU32 col = GetColorU32(((held && hovered) || (node->IsFocused && !hovered)) ? ImGuiCol_ButtonActive
8362 : hovered ? ImGuiCol_ButtonHovered
8364 window->DrawList->AddTriangleFilled(p, p +
ImVec2(unhide_sz_draw, 0.0f), p +
ImVec2(0.0f, unhide_sz_draw),
8369 if (window->ScrollbarX)
8370 Scrollbar(ImGuiAxis_X);
8371 if (window->ScrollbarY)
8372 Scrollbar(ImGuiAxis_Y);
8375 if (handle_borders_and_resize_grips && !(flags & ImGuiWindowFlags_NoResize))
8377 for (
int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
8379 const ImU32 col = resize_grip_col[resize_grip_n];
8380 if ((col & IM_COL32_A_MASK) == 0)
8383 const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
8384 const float border_inner = IM_ROUND(window_border_size * 0.5f);
8385 window->DrawList->PathLineTo(
8386 corner + grip.InnerDir * ((resize_grip_n & 1) ?
ImVec2(border_inner, resize_grip_draw_size)
8387 :
ImVec2(resize_grip_draw_size, border_inner)));
8388 window->DrawList->PathLineTo(
8389 corner + grip.InnerDir * ((resize_grip_n & 1) ?
ImVec2(resize_grip_draw_size, border_inner)
8390 :
ImVec2(border_inner, resize_grip_draw_size)));
8391 window->DrawList->PathArcToFast(
ImVec2(corner.x + grip.InnerDir.x * (window_rounding + border_inner),
8392 corner.y + grip.InnerDir.y * (window_rounding + border_inner)),
8393 window_rounding, grip.AngleMin12, grip.AngleMax12);
8394 window->DrawList->PathFillConvex(col);
8399 if (handle_borders_and_resize_grips && !window->DockNodeAsHost)
8400 RenderWindowOuterBorders(window);
8402 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
8407void ImGui::RenderWindowTitleBarContents(
ImGuiWindow *window,
const ImRect &title_bar_rect,
const char *name,
8412 ImGuiWindowFlags flags = window->Flags;
8414 const bool has_close_button = (p_open != NULL);
8415 const bool has_collapse_button =
8416 !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None);
8422 const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags;
8423 g.CurrentItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
8424 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
8428 float pad_l = style.FramePadding.x;
8429 float pad_r = style.FramePadding.x;
8430 float button_sz = g.FontSize;
8432 ImVec2 collapse_button_pos;
8433 if (has_close_button)
8436 ImVec2(title_bar_rect.Max.x - pad_r - button_sz, title_bar_rect.Min.y + style.FramePadding.y);
8437 pad_r += button_sz + style.ItemInnerSpacing.x;
8439 if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Right)
8441 collapse_button_pos =
8442 ImVec2(title_bar_rect.Max.x - pad_r - button_sz, title_bar_rect.Min.y + style.FramePadding.y);
8443 pad_r += button_sz + style.ItemInnerSpacing.x;
8445 if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Left)
8447 collapse_button_pos =
ImVec2(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y + style.FramePadding.y);
8448 pad_l += button_sz + style.ItemInnerSpacing.x;
8452 if (has_collapse_button)
8453 if (CollapseButton(window->GetID(
"#COLLAPSE"), collapse_button_pos, NULL))
8454 window->WantCollapseToggle =
8458 if (has_close_button)
8459 if (CloseButton(window->GetID(
"#CLOSE"), close_button_pos))
8462 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
8463 g.CurrentItemFlags = item_flags_backup;
8467 const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? button_sz * 0.80f : 0.0f;
8468 const ImVec2 text_size = CalcTextSize(name, NULL,
true) +
ImVec2(marker_size_x, 0.0f);
8472 if (pad_l > style.FramePadding.x)
8473 pad_l += g.Style.ItemInnerSpacing.x;
8474 if (pad_r > style.FramePadding.x)
8475 pad_r += g.Style.ItemInnerSpacing.x;
8476 if (style.WindowTitleAlign.x > 0.0f && style.WindowTitleAlign.x < 1.0f)
8479 ImSaturate(1.0f - ImFabs(style.WindowTitleAlign.x - 0.5f) * 2.0f);
8480 float pad_extend = ImMin(ImMax(pad_l, pad_r), title_bar_rect.GetWidth() - pad_l - pad_r - text_size.x);
8481 pad_l = ImMax(pad_l, pad_extend * centerness);
8482 pad_r = ImMax(pad_r, pad_extend * centerness);
8485 ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r,
8486 title_bar_rect.Max.y);
8487 ImRect clip_r(layout_r.Min.x, layout_r.Min.y,
8488 ImMin(layout_r.Max.x + g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x), layout_r.Max.y);
8489 if (flags & ImGuiWindowFlags_UnsavedDocument)
8493 ImClamp(layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x + text_size.x,
8494 layout_r.Min.x, layout_r.Max.x);
8495 marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f;
8496 if (marker_pos.x > layout_r.Min.x)
8498 RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text));
8499 clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (
int)(marker_size_x * 0.5f));
8504 RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r);
8507void ImGui::UpdateWindowParentAndRootLinks(
ImGuiWindow *window, ImGuiWindowFlags flags,
ImGuiWindow *parent_window)
8509 window->ParentWindow = parent_window;
8510 window->RootWindow = window->RootWindowPopupTree = window->RootWindowDockTree =
8511 window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
8512 if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
8514 window->RootWindowDockTree = parent_window->RootWindowDockTree;
8515 if (!window->DockIsActive && !(parent_window->Flags & ImGuiWindowFlags_DockNodeHost))
8516 window->RootWindow = parent_window->RootWindow;
8518 if (parent_window && (flags & ImGuiWindowFlags_Popup))
8519 window->RootWindowPopupTree = parent_window->RootWindowPopupTree;
8520 if (parent_window && !(flags & ImGuiWindowFlags_Modal) &&
8521 (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)))
8522 window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
8523 while (window->RootWindowForNav->ChildFlags & ImGuiChildFlags_NavFlattened)
8525 IM_ASSERT(window->RootWindowForNav->ParentWindow != NULL);
8526 window->RootWindowForNav = window->RootWindowForNav->ParentWindow;
8532void ImGui::UpdateWindowSkipRefresh(
ImGuiWindow *window)
8535 window->SkipRefresh =
false;
8536 if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasRefreshPolicy) == 0)
8538 if (g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_TryToAvoidRefresh)
8541 if (window->Appearing)
8545 if ((g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnHover) && g.HoveredWindow)
8546 if (window->RootWindow == g.HoveredWindow->RootWindow ||
8547 IsWindowWithinBeginStackOf(g.HoveredWindow->RootWindow, window))
8549 if ((g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnFocus) && g.NavWindow)
8550 if (window->RootWindow == g.NavWindow->RootWindow ||
8551 IsWindowWithinBeginStackOf(g.NavWindow->RootWindow, window))
8553 window->DrawList = NULL;
8554 window->SkipRefresh =
true;
8558static void SetWindowActiveForSkipRefresh(
ImGuiWindow *window)
8560 window->Active =
true;
8561 for (
ImGuiWindow *child : window->DC.ChildWindows)
8564 child->Active = child->SkipRefresh =
true;
8565 SetWindowActiveForSkipRefresh(child);
8581bool ImGui::Begin(
const char *name,
bool *p_open, ImGuiWindowFlags flags)
8585 IM_ASSERT(name != NULL && name[0] !=
'\0');
8586 IM_ASSERT(g.WithinFrameScope);
8588 g.FrameCountEnded !=
8593 const bool window_just_created = (window == NULL);
8594 if (window_just_created)
8595 window = CreateNewWindow(name, flags);
8598 if (g.DebugBreakInWindow == window->ID)
8602 if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
8603 flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
8605 const int current_frame = g.FrameCount;
8606 const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);
8607 window->IsFallbackWindow = (g.CurrentWindowStack.Size == 0 && g.WithinFrameScopeWithImplicitWindow);
8610 bool window_just_activated_by_user =
8611 (window->LastFrameActive <
8613 if (flags & ImGuiWindowFlags_Popup)
8615 ImGuiPopupData &popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
8616 window_just_activated_by_user |=
8619 window_just_activated_by_user |= (window != popup_ref.Window);
8623 const bool window_was_appearing = window->Appearing;
8624 if (first_begin_of_the_frame)
8626 UpdateWindowInFocusOrderList(window, window_just_created, flags);
8627 window->Appearing = window_just_activated_by_user;
8628 if (window->Appearing)
8629 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
true);
8630 window->FlagsPreviousFrame = window->Flags;
8631 window->Flags = (ImGuiWindowFlags)flags;
8632 window->ChildFlags =
8633 (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : 0;
8634 window->LastFrameActive = current_frame;
8635 window->LastTimeActive = (float)g.Time;
8636 window->BeginOrderWithinParent = 0;
8637 window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++);
8641 flags = window->Flags;
8647 IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL);
8648 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasDock)
8649 SetWindowDock(window, g.NextWindowData.DockId, g.NextWindowData.DockCond);
8650 if (first_begin_of_the_frame)
8652 bool has_dock_node = (window->DockId != 0 || window->DockNode != NULL);
8653 bool new_auto_dock_node = !has_dock_node && GetWindowAlwaysWantOwnTabBar(window);
8654 bool dock_node_was_visible = window->DockNodeIsVisible;
8655 bool dock_tab_was_visible = window->DockTabIsVisible;
8656 if (has_dock_node || new_auto_dock_node)
8658 BeginDocked(window, p_open);
8659 flags = window->Flags;
8660 if (window->DockIsActive)
8662 IM_ASSERT(window->DockNode != NULL);
8663 g.NextWindowData.HasFlags &=
8664 ~ImGuiNextWindowDataFlags_HasSizeConstraint;
8668 if (window->DockTabIsVisible && !dock_tab_was_visible && dock_node_was_visible && !window->Appearing &&
8669 !window_was_appearing)
8671 window->Appearing =
true;
8672 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
true);
8677 window->DockIsActive = window->DockNodeIsVisible = window->DockTabIsVisible =
false;
8683 ImGuiWindow *parent_window_in_stack = (window->DockIsActive && window->DockNode->HostWindow)
8684 ? window->DockNode->HostWindow
8685 : g.CurrentWindowStack.empty() ? NULL
8686 : g.CurrentWindowStack.back().Window;
8688 first_begin_of_the_frame
8689 ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL)
8690 : window->ParentWindow;
8691 IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
8694 if (window->IDStack.Size == 0)
8695 window->IDStack.push_back(window->ID);
8698 g.CurrentWindow = window;
8699 g.CurrentWindowStack.resize(g.CurrentWindowStack.Size + 1);
8701 window_stack_data.Window = window;
8702 window_stack_data.ParentLastItemDataBackup = g.LastItemData;
8703 window_stack_data.DisabledOverrideReenable =
8704 (flags & ImGuiWindowFlags_Tooltip) && (g.CurrentItemFlags & ImGuiItemFlags_Disabled);
8705 window_stack_data.DisabledOverrideReenableAlphaBackup = 0.0f;
8706 ErrorRecoveryStoreState(&window_stack_data.StackSizesInBegin);
8707 g.StackSizesInBeginForCurrentWindow = &window_stack_data.StackSizesInBegin;
8708 if (flags & ImGuiWindowFlags_ChildMenu)
8712 if (first_begin_of_the_frame)
8714 UpdateWindowParentAndRootLinks(window, flags, parent_window);
8715 window->ParentWindowInBeginStack = parent_window_in_stack;
8721 window->ParentWindowForFocusRoute = (window->RootWindow != window) ? parent_window_in_stack : NULL;
8722 if (window->ParentWindowForFocusRoute == NULL && window->DockNode != NULL)
8723 if (window->DockNode->MergedFlags & ImGuiDockNodeFlags_DockedWindowsInFocusRoute)
8724 window->ParentWindowForFocusRoute = window->DockNode->HostWindow;
8727 if (window->WindowClass.FocusRouteParentWindowId != 0)
8729 window->ParentWindowForFocusRoute = FindWindowByID(window->WindowClass.FocusRouteParentWindowId);
8730 IM_ASSERT(window->ParentWindowForFocusRoute != 0);
8734 window->FontWindowScaleParents =
8735 parent_window ? parent_window->FontWindowScaleParents * parent_window->FontWindowScale : 1.0f;
8739 PushFocusScope((window->ChildFlags & ImGuiChildFlags_NavFlattened) ? g.CurrentFocusScopeId : window->ID);
8740 window->NavRootFocusScopeId = g.CurrentFocusScopeId;
8743 if (flags & ImGuiWindowFlags_Popup)
8745 ImGuiPopupData &popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
8746 popup_ref.Window = window;
8747 popup_ref.ParentNavLayer = parent_window_in_stack->DC.NavLayerCurrent;
8748 g.BeginPopupStack.push_back(popup_ref);
8749 window->PopupId = popup_ref.PopupId;
8754 bool window_pos_set_by_api =
false;
8755 bool window_size_x_set_by_api =
false, window_size_y_set_by_api =
false;
8756 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos)
8758 window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0;
8759 if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f)
8763 window->SetWindowPosVal = g.NextWindowData.PosVal;
8764 window->SetWindowPosPivot = g.NextWindowData.PosPivotVal;
8765 window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
8769 SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond);
8772 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize)
8774 window_size_x_set_by_api =
8775 (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f);
8776 window_size_y_set_by_api =
8777 (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f);
8778 if ((window->ChildFlags & ImGuiChildFlags_ResizeX) &&
8779 (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) ==
8781 g.NextWindowData.SizeVal.x = window->SizeFull.x;
8782 if ((window->ChildFlags & ImGuiChildFlags_ResizeY) &&
8783 (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0)
8784 g.NextWindowData.SizeVal.y = window->SizeFull.y;
8785 SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond);
8787 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasScroll)
8789 if (g.NextWindowData.ScrollVal.x >= 0.0f)
8791 window->ScrollTarget.x = g.NextWindowData.ScrollVal.x;
8792 window->ScrollTargetCenterRatio.x = 0.0f;
8794 if (g.NextWindowData.ScrollVal.y >= 0.0f)
8796 window->ScrollTarget.y = g.NextWindowData.ScrollVal.y;
8797 window->ScrollTargetCenterRatio.y = 0.0f;
8800 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasContentSize)
8801 window->ContentSizeExplicit = g.NextWindowData.ContentSizeVal;
8802 else if (first_begin_of_the_frame)
8803 window->ContentSizeExplicit =
ImVec2(0.0f, 0.0f);
8804 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasWindowClass)
8805 window->WindowClass = g.NextWindowData.WindowClass;
8806 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasCollapsed)
8807 SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond);
8808 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasFocus)
8809 FocusWindow(window);
8810 if (window->Appearing)
8811 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing,
false);
8814 UpdateWindowSkipRefresh(window);
8817 if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
8818 BeginDisabledOverrideReenable();
8822 g.CurrentWindow = NULL;
8825 if (first_begin_of_the_frame && !window->SkipRefresh)
8828 const bool window_is_child_tooltip =
8829 (flags & ImGuiWindowFlags_ChildWindow) &&
8831 ImGuiWindowFlags_Tooltip);
8832 const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesCannotSkipItems > 0);
8833 window->Active =
true;
8834 window->HasCloseButton = (p_open != NULL);
8835 window->ClipRect =
ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX);
8836 window->IDStack.resize(1);
8837 window->DrawList->_ResetForNewFrame();
8838 window->DC.CurrentTableIdx = -1;
8839 if (flags & ImGuiWindowFlags_DockNodeHost)
8841 window->DrawList->ChannelsSplit(2);
8842 window->DrawList->ChannelsSetCurrent(
8843 DOCKING_HOST_DRAW_CHANNEL_FG);
8848 if (window->MemoryCompacted)
8849 GcAwakeTransientWindowBuffers(window);
8854 bool window_title_visible_elsewhere =
false;
8855 if ((window->Viewport && window->Viewport->Window == window) || (window->DockIsActive))
8856 window_title_visible_elsewhere =
true;
8857 else if (g.NavWindowingListWindow != NULL &&
8858 (flags & ImGuiWindowFlags_NoNavFocus) == 0)
8859 window_title_visible_elsewhere =
true;
8860 else if (flags & ImGuiWindowFlags_ChildMenu)
8861 window_title_visible_elsewhere =
true;
8862 if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0)
8864 size_t buf_len = (size_t)window->NameBufLen;
8865 window->Name = ImStrdupcpy(window->Name, &buf_len, name);
8866 window->NameBufLen = (int)buf_len;
8872 CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSizeIdeal);
8878 if (window->HiddenFramesCanSkipItems > 0)
8879 window->HiddenFramesCanSkipItems--;
8880 if (window->HiddenFramesCannotSkipItems > 0)
8881 window->HiddenFramesCannotSkipItems--;
8882 if (window->HiddenFramesForRenderOnly > 0)
8883 window->HiddenFramesForRenderOnly--;
8886 if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api))
8887 window->HiddenFramesCannotSkipItems = 1;
8892 if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
8894 window->HiddenFramesCannotSkipItems = 1;
8895 if (flags & ImGuiWindowFlags_AlwaysAutoResize)
8897 if (!window_size_x_set_by_api)
8898 window->Size.x = window->SizeFull.x = 0.f;
8899 if (!window_size_y_set_by_api)
8900 window->Size.y = window->SizeFull.y = 0.f;
8901 window->ContentSize = window->ContentSizeIdeal =
ImVec2(0.f, 0.f);
8908 WindowSelectViewport(window);
8909 SetCurrentViewport(window, window->Viewport);
8910 window->FontDpiScale =
8911 (g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts) ? window->Viewport->DpiScale : 1.0f;
8912 SetCurrentWindow(window);
8913 flags = window->Flags;
8918 if (!window->DockIsActive && (flags & ImGuiWindowFlags_ChildWindow))
8919 window->WindowBorderSize = style.ChildBorderSize;
8921 window->WindowBorderSize =
8922 ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal))
8923 ? style.PopupBorderSize
8924 : style.WindowBorderSize;
8925 window->WindowPadding = style.WindowPadding;
8926 if (!window->DockIsActive && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) &&
8927 !(window->ChildFlags & ImGuiChildFlags_AlwaysUseWindowPadding) && window->WindowBorderSize == 0.0f)
8928 window->WindowPadding =
ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
8931 window->DC.MenuBarOffset.x =
8932 ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
8933 window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
8934 window->TitleBarHeight =
8935 (flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : g.FontSize + g.Style.FramePadding.y * 2.0f;
8936 window->MenuBarHeight = (flags & ImGuiWindowFlags_MenuBar)
8937 ? window->DC.MenuBarOffset.y + g.FontSize + g.Style.FramePadding.y * 2.0f
8939 window->FontRefSize =
8945 bool use_current_size_for_scrollbar_x = window_just_created;
8946 bool use_current_size_for_scrollbar_y = window_just_created;
8947 if (window_size_x_set_by_api && window->ContentSizeExplicit.x != 0.0f)
8948 use_current_size_for_scrollbar_x =
true;
8949 if (window_size_y_set_by_api && window->ContentSizeExplicit.y != 0.0f)
8950 use_current_size_for_scrollbar_y =
true;
8955 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse) && !window->DockIsActive)
8959 ImRect title_bar_rect = window->TitleBarRect();
8960 if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && g.ActiveId == 0 &&
8961 IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
8962 if (g.IO.MouseClickedCount[0] == 2 && GetKeyOwner(ImGuiKey_MouseLeft) == ImGuiKeyOwner_NoOwner)
8963 window->WantCollapseToggle =
true;
8964 if (window->WantCollapseToggle)
8966 window->Collapsed = !window->Collapsed;
8967 if (!window->Collapsed)
8968 use_current_size_for_scrollbar_y =
true;
8969 MarkIniSettingsDirty(window);
8974 window->Collapsed =
false;
8976 window->WantCollapseToggle =
false;
8983 const ImVec2 scrollbar_sizes_from_last_frame = window->ScrollbarSizes;
8984 window->DecoOuterSizeX1 = 0.0f;
8985 window->DecoOuterSizeX2 = 0.0f;
8986 window->DecoOuterSizeY1 = window->TitleBarHeight + window->MenuBarHeight;
8987 window->DecoOuterSizeY2 = 0.0f;
8988 window->ScrollbarSizes =
ImVec2(0.0f, 0.0f);
8991 const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSizeIdeal);
8992 if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
8996 if (!window_size_x_set_by_api)
8998 window->SizeFull.x = size_auto_fit.x;
8999 use_current_size_for_scrollbar_x =
true;
9001 if (!window_size_y_set_by_api)
9003 window->SizeFull.y = size_auto_fit.y;
9004 use_current_size_for_scrollbar_y =
true;
9007 else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
9012 if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
9014 window->SizeFull.x =
9015 window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
9016 use_current_size_for_scrollbar_x =
true;
9018 if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
9020 window->SizeFull.y =
9021 window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
9022 use_current_size_for_scrollbar_y =
true;
9024 if (!window->Collapsed)
9025 MarkIniSettingsDirty(window);
9029 window->SizeFull = CalcWindowSizeAfterConstraint(window, window->SizeFull);
9030 window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize()
9036 if (window_just_activated_by_user)
9038 window->AutoPosLastDirection = ImGuiDir_None;
9039 if ((flags & ImGuiWindowFlags_Popup) != 0 && !(flags & ImGuiWindowFlags_Modal) &&
9040 !window_pos_set_by_api)
9041 window->Pos = g.BeginPopupStack.back().OpenPopupPos;
9045 if (flags & ImGuiWindowFlags_ChildWindow)
9047 IM_ASSERT(parent_window && parent_window->Active);
9048 window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size;
9049 parent_window->DC.ChildWindows.push_back(window);
9050 if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip)
9051 window->Pos = parent_window->DC.CursorPos;
9054 const bool window_pos_with_pivot =
9055 (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesCannotSkipItems == 0);
9056 if (window_pos_with_pivot)
9057 SetWindowPos(window, window->SetWindowPosVal - window->Size * window->SetWindowPosPivot,
9059 else if ((flags & ImGuiWindowFlags_ChildMenu) != 0)
9060 window->Pos = FindBestWindowPosForPopup(window);
9061 else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api &&
9062 window_just_appearing_after_hidden_for_resize)
9063 window->Pos = FindBestWindowPosForPopup(window);
9064 else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip)
9065 window->Pos = FindBestWindowPosForPopup(window);
9068 if (window->ViewportAllowPlatformMonitorExtend >= 0 && !window->ViewportOwned &&
9069 !(window->Viewport->Flags & ImGuiViewportFlags_IsMinimized))
9070 if (!window->Viewport->GetMainRect().Contains(window->Rect()))
9075 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size,
9076 ImGuiViewportFlags_NoFocusOnAppearing);
9080 SetCurrentViewport(window, window->Viewport);
9081 window->FontDpiScale =
9082 (g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts) ? window->Viewport->DpiScale : 1.0f;
9083 SetCurrentWindow(window);
9086 if (window->ViewportOwned)
9087 WindowSyncOwnedViewport(window, parent_window_in_stack);
9091 ImRect viewport_rect(window->Viewport->GetMainRect());
9092 ImRect viewport_work_rect(window->Viewport->GetWorkRect());
9093 ImVec2 visibility_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
9094 ImRect visibility_rect(viewport_work_rect.Min + visibility_padding,
9095 viewport_work_rect.Max - visibility_padding);
9101 if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow))
9103 if (!window->ViewportOwned && viewport_rect.GetWidth() > 0 && viewport_rect.GetHeight() > 0.0f)
9105 ClampWindowPos(window, visibility_rect);
9107 else if (window->ViewportOwned && g.PlatformIO.Monitors.Size > 0)
9109 if (g.MovingWindow != NULL && window->RootWindowDockTree == g.MovingWindow->RootWindowDockTree)
9112 visibility_rect = g.PlatformMonitorsFullWorkRect;
9120 visibility_rect =
ImRect(monitor->WorkPos, monitor->WorkPos + monitor->WorkSize);
9122 visibility_rect.Expand(-visibility_padding);
9123 ClampWindowPos(window, visibility_rect);
9126 window->Pos = ImTrunc(window->Pos);
9130 if (window->ViewportOwned || window->DockIsActive)
9131 window->WindowRounding = 0.0f;
9133 window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding
9134 : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal))
9135 ? style.PopupRounding
9136 : style.WindowRounding;
9144 bool want_focus =
false;
9145 if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))
9147 if (flags & ImGuiWindowFlags_Popup)
9149 else if ((window->DockIsActive || (flags & ImGuiWindowFlags_ChildWindow) == 0) &&
9150 !(flags & ImGuiWindowFlags_Tooltip))
9155#ifdef IMGUI_ENABLE_TEST_ENGINE
9156 if (g.TestEngineHookItems)
9158 IM_ASSERT(window->IDStack.Size == 1);
9159 window->IDStack.Size = 0;
9161 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
9162 IMGUI_TEST_ENGINE_ITEM_ADD(window->ID, window->Rect(), NULL);
9163 IMGUI_TEST_ENGINE_ITEM_INFO(window->ID, window->Name,
9164 (g.HoveredWindow == window) ? ImGuiItemStatusFlags_HoveredRect : 0);
9165 window->IDStack.Size = 1;
9166 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
9171 const bool handle_borders_and_resize_grips = (window->DockNodeAsHost || !window->DockIsActive);
9174 int border_hovered = -1, border_held = -1;
9175 ImU32 resize_grip_col[4] = {};
9176 const int resize_grip_count =
9177 ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) ? 0
9178 : g.IO.ConfigWindowsResizeFromEdges
9181 const float resize_grip_draw_size =
9182 IM_TRUNC(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
9183 if (handle_borders_and_resize_grips && !window->Collapsed)
9184 if (
int auto_fit_mask = UpdateWindowManualResize(window, size_auto_fit, &border_hovered, &border_held,
9185 resize_grip_count, &resize_grip_col[0], visibility_rect))
9187 if (auto_fit_mask & (1 << ImGuiAxis_X))
9188 use_current_size_for_scrollbar_x =
true;
9189 if (auto_fit_mask & (1 << ImGuiAxis_Y))
9190 use_current_size_for_scrollbar_y =
true;
9192 window->ResizeBorderHovered = (
signed char)border_hovered;
9193 window->ResizeBorderHeld = (
signed char)border_held;
9196 if (window->ViewportOwned)
9198 if (!window->Viewport->PlatformRequestMove)
9199 window->Viewport->Pos = window->Pos;
9200 if (!window->Viewport->PlatformRequestResize)
9201 window->Viewport->Size = window->Size;
9202 window->Viewport->UpdateWorkRect();
9203 viewport_rect = window->Viewport->GetMainRect();
9207 window->ViewportPos = window->Viewport->Pos;
9213 if (!window->Collapsed)
9218 ImVec2 avail_size_from_current_frame =
9219 ImVec2(window->SizeFull.x, window->SizeFull.y - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2));
9220 ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + scrollbar_sizes_from_last_frame;
9221 ImVec2 needed_size_from_last_frame =
9222 window_just_created ?
ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f;
9223 float size_x_for_scrollbars =
9224 use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x;
9225 float size_y_for_scrollbars =
9226 use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y;
9227 bool scrollbar_x_prev = window->ScrollbarX;
9230 window->ScrollbarY =
9231 (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) ||
9232 ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
9233 window->ScrollbarX =
9234 (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) ||
9235 ((needed_size_from_last_frame.x >
9236 size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) &&
9237 !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
9246 window->ScrollbarXStabilizeToggledHistory <<= 1;
9247 window->ScrollbarXStabilizeToggledHistory |= (scrollbar_x_prev != window->ScrollbarX) ? 0x01 : 0x00;
9248 const bool scrollbar_x_stabilize =
9249 (window->ScrollbarXStabilizeToggledHistory != 0) &&
9250 ImCountSetBits(window->ScrollbarXStabilizeToggledHistory) >= 4;
9251 if (scrollbar_x_stabilize)
9252 window->ScrollbarX =
true;
9255 window->ScrollbarXStabilizeEnabled = scrollbar_x_stabilize;
9257 if (window->ScrollbarX && !window->ScrollbarY)
9258 window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars - style.ScrollbarSize) &&
9259 !(flags & ImGuiWindowFlags_NoScrollbar);
9260 window->ScrollbarSizes =
ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f,
9261 window->ScrollbarX ? style.ScrollbarSize : 0.0f);
9264 window->DecoOuterSizeX2 += window->ScrollbarSizes.x;
9265 window->DecoOuterSizeY2 += window->ScrollbarSizes.y;
9278 ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip)
9279 ? parent_window->ClipRect
9281 const ImRect outer_rect = window->Rect();
9282 const ImRect title_bar_rect = window->TitleBarRect();
9283 window->OuterRectClipped = outer_rect;
9284 if (window->DockIsActive)
9285 window->OuterRectClipped.Min.y += window->TitleBarHeight;
9286 window->OuterRectClipped.ClipWith(host_rect);
9294 window->InnerRect.Min.x = window->Pos.x + window->DecoOuterSizeX1;
9295 window->InnerRect.Min.y = window->Pos.y + window->DecoOuterSizeY1;
9296 window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->DecoOuterSizeX2;
9297 window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->DecoOuterSizeY2;
9309 float top_border_size =
9310 (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize
9311 : window->WindowBorderSize);
9317 window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + window->WindowBorderSize * 0.5f);
9318 window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size * 0.5f);
9319 window->InnerClipRect.Max.x = ImFloor(window->InnerRect.Max.x - window->WindowBorderSize * 0.5f);
9320 window->InnerClipRect.Max.y = ImFloor(window->InnerRect.Max.y - window->WindowBorderSize * 0.5f);
9321 window->InnerClipRect.ClipWithFull(host_rect);
9324 if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) &&
9325 !(flags & ImGuiWindowFlags_AlwaysAutoResize))
9326 window->ItemWidthDefault = ImTrunc(window->Size.x * 0.65f);
9328 window->ItemWidthDefault = ImTrunc(g.FontSize * 16.0f);
9335 window->ScrollMax.x =
9336 ImMax(0.0f, window->ContentSize.x + window->WindowPadding.x * 2.0f - window->InnerRect.GetWidth());
9337 window->ScrollMax.y =
9338 ImMax(0.0f, window->ContentSize.y + window->WindowPadding.y * 2.0f - window->InnerRect.GetHeight());
9341 window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window);
9342 window->ScrollTarget =
ImVec2(FLT_MAX, FLT_MAX);
9343 window->DecoInnerSizeX1 = window->DecoInnerSizeY1 = 0.0f;
9348 IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0);
9349 window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
9350 PushClipRect(host_rect.Min, host_rect.Max,
false);
9357 const bool is_undocked_or_docked_visible = !window->DockIsActive || window->DockTabIsVisible;
9358 if (is_undocked_or_docked_visible)
9360 bool render_decorations_in_parent =
false;
9361 if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip)
9368 parent_window->DC.ChildWindows.Size >= 2
9369 ? parent_window->DC.ChildWindows[parent_window->DC.ChildWindows.Size - 2]
9371 bool previous_child_overlapping =
9372 previous_child ? previous_child->Rect().Overlaps(window->Rect()) :
false;
9373 bool parent_is_empty = (parent_window->DrawList->VtxBuffer.Size == 0);
9374 if (window->DrawList->CmdBuffer.back().ElemCount == 0 && !parent_is_empty &&
9375 !previous_child_overlapping)
9376 render_decorations_in_parent =
true;
9378 if (render_decorations_in_parent)
9379 window->DrawList = parent_window->DrawList;
9382 const ImGuiWindow *window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow;
9383 const bool title_bar_is_highlight =
9385 (window_to_highlight &&
9386 (window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight ||
9387 (window->DockNode && window->DockNode == window_to_highlight->DockNode)));
9388 RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, handle_borders_and_resize_grips,
9389 resize_grip_count, resize_grip_col, resize_grip_draw_size);
9391 if (render_decorations_in_parent)
9392 window->DrawList = &window->DrawListInst;
9402 const bool allow_scrollbar_x =
9403 !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar);
9404 const bool allow_scrollbar_y = !(flags & ImGuiWindowFlags_NoScrollbar);
9405 const float work_rect_size_x =
9406 (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x
9407 : ImMax(allow_scrollbar_x ? window->ContentSize.x : 0.0f,
9408 window->Size.x - window->WindowPadding.x * 2.0f -
9409 (window->DecoOuterSizeX1 + window->DecoOuterSizeX2)));
9410 const float work_rect_size_y =
9411 (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y
9412 : ImMax(allow_scrollbar_y ? window->ContentSize.y : 0.0f,
9413 window->Size.y - window->WindowPadding.y * 2.0f -
9414 (window->DecoOuterSizeY1 + window->DecoOuterSizeY2)));
9415 window->WorkRect.Min.x = ImTrunc(window->InnerRect.Min.x - window->Scroll.x +
9416 ImMax(window->WindowPadding.x, window->WindowBorderSize));
9417 window->WorkRect.Min.y = ImTrunc(window->InnerRect.Min.y - window->Scroll.y +
9418 ImMax(window->WindowPadding.y, window->WindowBorderSize));
9419 window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x;
9420 window->WorkRect.Max.y = window->WorkRect.Min.y + work_rect_size_y;
9421 window->ParentWorkRect = window->WorkRect;
9428 window->ContentRegionRect.Min.x =
9429 window->Pos.x - window->Scroll.x + window->WindowPadding.x + window->DecoOuterSizeX1;
9430 window->ContentRegionRect.Min.y =
9431 window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->DecoOuterSizeY1;
9432 window->ContentRegionRect.Max.x =
9433 window->ContentRegionRect.Min.x + (window->ContentSizeExplicit.x != 0.0f
9434 ? window->ContentSizeExplicit.x
9435 : (window->Size.x - window->WindowPadding.x * 2.0f -
9436 (window->DecoOuterSizeX1 + window->DecoOuterSizeX2)));
9437 window->ContentRegionRect.Max.y =
9438 window->ContentRegionRect.Min.y + (window->ContentSizeExplicit.y != 0.0f
9439 ? window->ContentSizeExplicit.y
9440 : (window->Size.y - window->WindowPadding.y * 2.0f -
9441 (window->DecoOuterSizeY1 + window->DecoOuterSizeY2)));
9446 window->DC.Indent.x = window->DecoOuterSizeX1 + window->WindowPadding.x - window->Scroll.x;
9447 window->DC.GroupOffset.x = 0.0f;
9448 window->DC.ColumnsOffset.x = 0.0f;
9453 double start_pos_highp_x = (double)window->Pos.x + window->WindowPadding.x - (
double)window->Scroll.x +
9454 window->DecoOuterSizeX1 + window->DC.ColumnsOffset.x;
9455 double start_pos_highp_y =
9456 (double)window->Pos.y + window->WindowPadding.y - (
double)window->Scroll.y + window->DecoOuterSizeY1;
9457 window->DC.CursorStartPos =
ImVec2((
float)start_pos_highp_x, (
float)start_pos_highp_y);
9458 window->DC.CursorStartPosLossyness =
ImVec2((
float)(start_pos_highp_x - window->DC.CursorStartPos.x),
9459 (
float)(start_pos_highp_y - window->DC.CursorStartPos.y));
9460 window->DC.CursorPos = window->DC.CursorStartPos;
9461 window->DC.CursorPosPrevLine = window->DC.CursorPos;
9462 window->DC.CursorMaxPos = window->DC.CursorStartPos;
9463 window->DC.IdealMaxPos = window->DC.CursorStartPos;
9464 window->DC.CurrLineSize = window->DC.PrevLineSize =
ImVec2(0.0f, 0.0f);
9465 window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
9466 window->DC.IsSameLine = window->DC.IsSetPos =
false;
9468 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
9469 window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext;
9470 window->DC.NavLayersActiveMaskNext = 0x00;
9471 window->DC.NavIsScrollPushableX =
true;
9472 window->DC.NavHideHighlightOneFrame =
false;
9473 window->DC.NavWindowHasScrollY = (window->ScrollMax.y > 0.0f);
9475 window->DC.MenuBarAppending =
false;
9476 window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user);
9477 window->DC.TreeDepth = 0;
9478 window->DC.TreeHasStackDataDepthMask = 0x00;
9479 window->DC.ChildWindows.resize(0);
9480 window->DC.StateStorage = &window->StateStorage;
9481 window->DC.CurrentColumns = NULL;
9482 window->DC.LayoutType = ImGuiLayoutType_Vertical;
9483 window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
9485 window->DC.ItemWidth = window->ItemWidthDefault;
9486 window->DC.TextWrapPos = -1.0f;
9487 window->DC.ItemWidthStack.resize(0);
9488 window->DC.TextWrapPosStack.resize(0);
9489 if (flags & ImGuiWindowFlags_Modal)
9490 window->DC.ModalDimBgColor = ColorConvertFloat4ToU32(GetStyleColorVec4(ImGuiCol_ModalWindowDimBg));
9492 if (window->AutoFitFramesX > 0)
9493 window->AutoFitFramesX--;
9494 if (window->AutoFitFramesY > 0)
9495 window->AutoFitFramesY--;
9498 g.NextWindowData.ClearFlags();
9506 FocusWindow(window, ImGuiFocusRequestFlags_UnlessBelowModal);
9507 if (want_focus && window == g.NavWindow)
9513 if (p_open != NULL && window->Viewport->PlatformRequestClose && window->Viewport != GetMainViewport())
9515 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Window '%s' closed by PlatformRequestClose\n", window->Name);
9517 g.NavWindowingToggleLayer =
9525 if (g.IO.ConfigWindowsCopyContentsWithCtrlC)
9526 if (g.NavWindow && g.NavWindow->RootWindow == window && g.ActiveId == 0 &&
9527 Shortcut(ImGuiMod_Ctrl | ImGuiKey_C))
9531 if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
9532 RenderWindowTitleBarContents(window,
9533 ImRect(title_bar_rect.Min.x + window->WindowBorderSize, title_bar_rect.Min.y,
9534 title_bar_rect.Max.x - window->WindowBorderSize, title_bar_rect.Max.y),
9536 else if (!(flags & ImGuiWindowFlags_NoTitleBar) && window->DockIsActive)
9537 LogText(
"%.*s\n", (
int)(FindRenderedTextEnd(window->Name) - window->Name), window->Name);
9540 window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0;
9542 if (flags & ImGuiWindowFlags_Tooltip)
9543 g.TooltipPreviousWindow = window;
9545 if (g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable)
9550 if (g.MovingWindow == window && (window->RootWindowDockTree->Flags & ImGuiWindowFlags_NoDocking) == 0)
9551 BeginDockableDragDropSource(window);
9555 if (g.DragDropActive && !(flags & ImGuiWindowFlags_NoDocking))
9556 if (g.MovingWindow == NULL || g.MovingWindow->RootWindowDockTree != window)
9557 if ((window == window->RootWindowDockTree) && !(window->Flags & ImGuiWindowFlags_DockNodeHost))
9558 BeginDockableDragDropTarget(window);
9563 window->DC.WindowItemStatusFlags = ImGuiItemStatusFlags_None;
9564 window->DC.WindowItemStatusFlags |=
9565 IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max,
false) ? ImGuiItemStatusFlags_HoveredRect : 0;
9566 SetLastItemDataForWindow(window, title_bar_rect);
9569#ifndef IMGUI_DISABLE_DEBUG_TOOLS
9570 if (g.DebugLocateId != 0 && (window->ID == g.DebugLocateId || window->MoveId == g.DebugLocateId))
9571 DebugLocateItemResolveWithLastItem();
9575#ifdef IMGUI_ENABLE_TEST_ENGINE
9576 if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
9578 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
9579 IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.ID, g.LastItemData.Rect, &g.LastItemData);
9580 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
9587 if (window->SkipRefresh)
9588 SetWindowActiveForSkipRefresh(window);
9591 SetCurrentViewport(window, window->Viewport);
9592 SetCurrentWindow(window);
9593 g.NextWindowData.ClearFlags();
9594 SetLastItemDataForWindow(window, window->TitleBarRect());
9597 if (!(flags & ImGuiWindowFlags_DockNodeHost) && !window->SkipRefresh)
9598 PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max,
true);
9602 window->WriteAccessed =
false;
9603 window->BeginCount++;
9606 if (first_begin_of_the_frame && !window->SkipRefresh)
9613 if (window->DockIsActive && !window->DockTabIsVisible)
9615 if (window->LastFrameJustFocused == g.FrameCount)
9616 window->HiddenFramesCannotSkipItems = 1;
9618 window->HiddenFramesCanSkipItems = 1;
9621 if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ChildMenu))
9626 IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0 || window->DockIsActive);
9627 const bool nav_request =
9628 (window->ChildFlags & ImGuiChildFlags_NavFlattened) &&
9629 (g.NavAnyRequest && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav);
9630 if (!g.LogEnabled && !nav_request)
9631 if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x ||
9632 window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y)
9634 if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
9635 window->HiddenFramesCannotSkipItems = 1;
9637 window->HiddenFramesCanSkipItems = 1;
9641 if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0))
9642 window->HiddenFramesCanSkipItems = 1;
9643 if (parent_window && parent_window->HiddenFramesCannotSkipItems > 0)
9644 window->HiddenFramesCannotSkipItems = 1;
9649 if (style.Alpha <= 0.0f)
9650 window->HiddenFramesCanSkipItems = 1;
9653 bool hidden_regular = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0);
9654 window->Hidden = hidden_regular || (window->HiddenFramesForRenderOnly > 0);
9657 if (window->DisableInputsFrames > 0)
9659 window->DisableInputsFrames--;
9660 window->Flags |= ImGuiWindowFlags_NoInputs;
9664 bool skip_items =
false;
9665 if (window->Collapsed || !window->Active || hidden_regular)
9666 if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesCannotSkipItems <= 0)
9668 window->SkipItems = skip_items;
9671 if (window->SkipItems)
9672 window->DC.NavLayersActiveMaskNext = window->DC.NavLayersActiveMask;
9678 if (window->SkipItems && !window->Appearing)
9679 IM_ASSERT(window->Appearing ==
9682 else if (first_begin_of_the_frame)
9685 window->SkipItems =
true;
9691#ifndef IMGUI_DISABLE_DEBUG_TOOLS
9692 if (!window->IsFallbackWindow)
9693 if ((g.IO.ConfigDebugBeginReturnValueOnce && window_just_created) ||
9694 (g.IO.ConfigDebugBeginReturnValueLoop && g.DebugBeginReturnValueCullDepth == g.CurrentWindowStack.Size))
9696 if (window->AutoFitFramesX > 0)
9698 window->AutoFitFramesX++;
9700 if (window->AutoFitFramesY > 0)
9702 window->AutoFitFramesY++;
9708 return !window->SkipItems;
9717 if (g.CurrentWindowStack.Size <= 1 && g.WithinFrameScopeWithImplicitWindow)
9719 IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size > 1,
"Calling End() too many times!");
9725 if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_DockNodeHost) &&
9726 !window->DockIsActive)
9727 IM_ASSERT_USER_ERROR(g.WithinEndChildID == window->ID,
"Must call EndChild() and not End()!");
9730 if (window->DC.CurrentColumns)
9732 if (!(window->Flags & ImGuiWindowFlags_DockNodeHost) && !window->SkipRefresh)
9735 if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
9736 EndDisabledOverrideReenable();
9738 if (window->SkipRefresh)
9740 IM_ASSERT(window->DrawList == NULL);
9741 window->DrawList = &window->DrawListInst;
9745 if (g.LogWindow == window)
9748 if (window->DC.IsSetPos)
9749 ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
9752 if (window->DockNode && window->DockTabIsVisible)
9753 if (
ImGuiWindow *host_window = window->DockNode->HostWindow)
9754 host_window->DC.CursorMaxPos = window->DC.CursorMaxPos + window->WindowPadding - host_window->WindowPadding;
9757 g.LastItemData = window_stack_data.ParentLastItemDataBackup;
9758 if (window->Flags & ImGuiWindowFlags_ChildMenu)
9760 if (window->Flags & ImGuiWindowFlags_Popup)
9761 g.BeginPopupStack.pop_back();
9764 if (g.IO.ConfigErrorRecovery)
9765 ErrorRecoveryTryToRecoverWindowState(&window_stack_data.StackSizesInBegin);
9767 g.CurrentWindowStack.pop_back();
9768 SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
9769 if (g.CurrentWindow)
9770 SetCurrentViewport(g.CurrentWindow, g.CurrentWindow->Viewport);
9774void ImGui::SetCurrentFont(
ImFont *font)
9780 IM_ASSERT(font->Scale > 0.0f);
9782 g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale);
9783 g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
9784 g.FontScale = g.FontSize / g.Font->FontSize;
9787 g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel;
9788 g.DrawListSharedData.TexUvLines = atlas->TexUvLines;
9789 g.DrawListSharedData.Font = g.Font;
9790 g.DrawListSharedData.FontSize = g.FontSize;
9791 g.DrawListSharedData.FontScale = g.FontScale;
9802void ImGui::PushFont(
ImFont *font)
9806 font = GetDefaultFont();
9807 g.FontStack.push_back(font);
9808 SetCurrentFont(font);
9809 g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
9812void ImGui::PopFont()
9815 if (g.FontStack.Size <= 0)
9817 IM_ASSERT_USER_ERROR(0,
"Calling PopFont() too many times!");
9820 g.FontStack.pop_back();
9821 ImFont *font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
9822 SetCurrentFont(font);
9823 g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
9826void ImGui::PushItemFlag(ImGuiItemFlags option,
bool enabled)
9829 ImGuiItemFlags item_flags = g.CurrentItemFlags;
9830 IM_ASSERT(item_flags == g.ItemFlagsStack.back());
9832 item_flags |= option;
9834 item_flags &= ~option;
9835 g.CurrentItemFlags = item_flags;
9836 g.ItemFlagsStack.push_back(item_flags);
9839void ImGui::PopItemFlag()
9842 if (g.ItemFlagsStack.Size <= 1)
9844 IM_ASSERT_USER_ERROR(0,
"Calling PopItemFlag() too many times!");
9847 g.ItemFlagsStack.pop_back();
9848 g.CurrentItemFlags = g.ItemFlagsStack.back();
9862void ImGui::BeginDisabled(
bool disabled)
9865 bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
9866 if (!was_disabled && disabled)
9868 g.DisabledAlphaBackup = g.Style.Alpha;
9870 g.Style.DisabledAlpha;
9872 if (was_disabled || disabled)
9873 g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
9874 g.ItemFlagsStack.push_back(g.CurrentItemFlags);
9875 g.DisabledStackSize++;
9878void ImGui::EndDisabled()
9881 if (g.DisabledStackSize <= 0)
9883 IM_ASSERT_USER_ERROR(0,
"Calling EndDisabled() too many times!");
9886 g.DisabledStackSize--;
9887 bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
9889 g.ItemFlagsStack.pop_back();
9890 g.CurrentItemFlags = g.ItemFlagsStack.back();
9891 if (was_disabled && (g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0)
9892 g.Style.Alpha = g.DisabledAlphaBackup;
9898void ImGui::BeginDisabledOverrideReenable()
9901 IM_ASSERT(g.CurrentItemFlags & ImGuiItemFlags_Disabled);
9902 g.CurrentWindowStack.back().DisabledOverrideReenableAlphaBackup = g.Style.Alpha;
9903 g.Style.Alpha = g.DisabledAlphaBackup;
9904 g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled;
9905 g.ItemFlagsStack.push_back(g.CurrentItemFlags);
9906 g.DisabledStackSize++;
9909void ImGui::EndDisabledOverrideReenable()
9912 g.DisabledStackSize--;
9913 IM_ASSERT(g.DisabledStackSize > 0);
9914 g.ItemFlagsStack.pop_back();
9915 g.CurrentItemFlags = g.ItemFlagsStack.back();
9916 g.Style.Alpha = g.CurrentWindowStack.back().DisabledOverrideReenableAlphaBackup;
9919void ImGui::PushTextWrapPos(
float wrap_pos_x)
9923 window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos);
9924 window->DC.TextWrapPos = wrap_pos_x;
9927void ImGui::PopTextWrapPos()
9931 if (window->DC.TextWrapPosStack.Size <= 0)
9933 IM_ASSERT_USER_ERROR(0,
"Calling PopTextWrapPos() too many times!");
9936 window->DC.TextWrapPos = window->DC.TextWrapPosStack.back();
9937 window->DC.TextWrapPosStack.pop_back();
9943 while (last_window != window)
9945 last_window = window;
9946 window = window->RootWindow;
9947 if (popup_hierarchy)
9948 window = window->RootWindowPopupTree;
9950 window = window->RootWindowDockTree;
9956 bool dock_hierarchy)
9958 ImGuiWindow *window_root = GetCombinedRootWindow(window, popup_hierarchy, dock_hierarchy);
9959 if (window_root == potential_parent)
9961 while (window != NULL)
9963 if (window == potential_parent)
9965 if (window == window_root)
9967 window = window->ParentWindow;
9974 if (window->RootWindow == potential_parent)
9976 while (window != NULL)
9978 if (window == potential_parent)
9980 window = window->ParentWindowInBeginStack;
9991 const int display_layer_delta = GetWindowDisplayLayer(potential_above) - GetWindowDisplayLayer(potential_below);
9992 if (display_layer_delta != 0)
9993 return display_layer_delta > 0;
9995 for (
int i = g.Windows.Size - 1; i >= 0; i--)
9998 if (candidate_window == potential_above)
10000 if (candidate_window == potential_below)
10010bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
10013 IM_ASSERT_USER_ERROR((flags & ~ImGuiHoveredFlags_AllowedMaskForIsWindowHovered) == 0,
10014 "Invalid flags for IsWindowHovered()!");
10018 if (ref_window == NULL)
10021 if ((flags & ImGuiHoveredFlags_AnyWindow) == 0)
10023 IM_ASSERT(cur_window);
10024 const bool popup_hierarchy = (flags & ImGuiHoveredFlags_NoPopupHierarchy) == 0;
10025 const bool dock_hierarchy = (flags & ImGuiHoveredFlags_DockHierarchy) != 0;
10026 if (flags & ImGuiHoveredFlags_RootWindow)
10027 cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
10030 if (flags & ImGuiHoveredFlags_ChildWindows)
10031 result = IsWindowChildOf(ref_window, cur_window, popup_hierarchy, dock_hierarchy);
10033 result = (ref_window == cur_window);
10038 if (!IsWindowContentHoverable(ref_window, flags))
10040 if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
10041 if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != ref_window->MoveId)
10049 if (flags & ImGuiHoveredFlags_ForTooltip)
10050 flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipMouse);
10051 if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverWindowUnlockedStationaryId != ref_window->ID)
10057ImGuiID ImGui::GetWindowDockID()
10060 return g.CurrentWindow->DockId;
10063bool ImGui::IsWindowDocked()
10066 return g.CurrentWindow->DockIsActive;
10069float ImGui::GetWindowWidth()
10072 return window->Size.x;
10075float ImGui::GetWindowHeight()
10078 return window->Size.y;
10081ImVec2 ImGui::GetWindowPos()
10085 return window->Pos;
10088void ImGui::SetWindowPos(
ImGuiWindow *window,
const ImVec2 &pos, ImGuiCond cond)
10091 if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
10094 IM_ASSERT(cond == 0 ||
10095 ImIsPowerOfTwo(cond));
10096 window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
10097 window->SetWindowPosVal =
ImVec2(FLT_MAX, FLT_MAX);
10100 const ImVec2 old_pos = window->Pos;
10101 window->Pos = ImTrunc(pos);
10102 ImVec2 offset = window->Pos - old_pos;
10103 if (offset.x == 0.0f && offset.y == 0.0f)
10105 MarkIniSettingsDirty(window);
10108 window->DC.CursorPos += offset;
10110 window->DC.CursorMaxPos += offset;
10112 window->DC.IdealMaxPos += offset;
10113 window->DC.CursorStartPos += offset;
10116void ImGui::SetWindowPos(
const ImVec2 &pos, ImGuiCond cond)
10119 SetWindowPos(window, pos, cond);
10122void ImGui::SetWindowPos(
const char *name,
const ImVec2 &pos, ImGuiCond cond)
10124 if (
ImGuiWindow *window = FindWindowByName(name))
10125 SetWindowPos(window, pos, cond);
10128ImVec2 ImGui::GetWindowSize()
10131 return window->Size;
10134void ImGui::SetWindowSize(
ImGuiWindow *window,
const ImVec2 &size, ImGuiCond cond)
10137 if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
10140 IM_ASSERT(cond == 0 ||
10141 ImIsPowerOfTwo(cond));
10142 window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
10146 if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || window->Appearing ||
10147 (window->ChildFlags & ImGuiChildFlags_AlwaysAutoResize) != 0)
10148 window->AutoFitFramesX = (size.x <= 0.0f) ? 2 : 0;
10149 if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || window->Appearing ||
10150 (window->ChildFlags & ImGuiChildFlags_AlwaysAutoResize) != 0)
10151 window->AutoFitFramesY = (size.y <= 0.0f) ? 2 : 0;
10154 ImVec2 old_size = window->SizeFull;
10155 if (size.x <= 0.0f)
10156 window->AutoFitOnlyGrows =
false;
10158 window->SizeFull.x = IM_TRUNC(size.x);
10159 if (size.y <= 0.0f)
10160 window->AutoFitOnlyGrows =
false;
10162 window->SizeFull.y = IM_TRUNC(size.y);
10163 if (old_size.x != window->SizeFull.x || old_size.y != window->SizeFull.y)
10164 MarkIniSettingsDirty(window);
10167void ImGui::SetWindowSize(
const ImVec2 &size, ImGuiCond cond)
10169 SetWindowSize(GImGui->CurrentWindow, size, cond);
10172void ImGui::SetWindowSize(
const char *name,
const ImVec2 &size, ImGuiCond cond)
10174 if (
ImGuiWindow *window = FindWindowByName(name))
10175 SetWindowSize(window, size, cond);
10178void ImGui::SetWindowCollapsed(
ImGuiWindow *window,
bool collapsed, ImGuiCond cond)
10181 if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)
10183 window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
10186 if (window->WantCollapseToggle)
10187 window->Collapsed ^= 1;
10188 window->WantCollapseToggle = (window->Collapsed != collapsed);
10193 IM_ASSERT(window->HitTestHoleSize.x == 0);
10194 window->HitTestHoleSize =
ImVec2ih(size);
10195 window->HitTestHoleOffset =
ImVec2ih(pos - window->Pos);
10198void ImGui::SetWindowHiddenAndSkipItemsForCurrentFrame(
ImGuiWindow *window)
10200 window->Hidden = window->SkipItems =
true;
10201 window->HiddenFramesCanSkipItems = 1;
10204void ImGui::SetWindowCollapsed(
bool collapsed, ImGuiCond cond)
10206 SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond);
10209bool ImGui::IsWindowCollapsed()
10212 return window->Collapsed;
10215bool ImGui::IsWindowAppearing()
10218 return window->Appearing;
10221void ImGui::SetWindowCollapsed(
const char *name,
bool collapsed, ImGuiCond cond)
10223 if (
ImGuiWindow *window = FindWindowByName(name))
10224 SetWindowCollapsed(window, collapsed, cond);
10227void ImGui::SetNextWindowPos(
const ImVec2 &pos, ImGuiCond cond,
const ImVec2 &pivot)
10230 IM_ASSERT(cond == 0 ||
10231 ImIsPowerOfTwo(cond));
10232 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasPos;
10233 g.NextWindowData.PosVal = pos;
10234 g.NextWindowData.PosPivotVal = pivot;
10235 g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
10236 g.NextWindowData.PosUndock =
true;
10239void ImGui::SetNextWindowSize(
const ImVec2 &size, ImGuiCond cond)
10242 IM_ASSERT(cond == 0 ||
10243 ImIsPowerOfTwo(cond));
10244 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasSize;
10245 g.NextWindowData.SizeVal = size;
10246 g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
10254void ImGui::SetNextWindowSizeConstraints(
const ImVec2 &size_min,
const ImVec2 &size_max,
10255 ImGuiSizeCallback custom_callback,
void *custom_callback_user_data)
10258 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
10259 g.NextWindowData.SizeConstraintRect =
ImRect(size_min, size_max);
10260 g.NextWindowData.SizeCallback = custom_callback;
10261 g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
10267void ImGui::SetNextWindowContentSize(
const ImVec2 &size)
10270 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasContentSize;
10271 g.NextWindowData.ContentSizeVal = ImTrunc(size);
10274void ImGui::SetNextWindowScroll(
const ImVec2 &scroll)
10277 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasScroll;
10278 g.NextWindowData.ScrollVal = scroll;
10281void ImGui::SetNextWindowCollapsed(
bool collapsed, ImGuiCond cond)
10284 IM_ASSERT(cond == 0 ||
10285 ImIsPowerOfTwo(cond));
10286 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasCollapsed;
10287 g.NextWindowData.CollapsedVal = collapsed;
10288 g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
10291void ImGui::SetNextWindowBgAlpha(
float alpha)
10294 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasBgAlpha;
10295 g.NextWindowData.BgAlphaVal = alpha;
10298void ImGui::SetNextWindowViewport(ImGuiID
id)
10301 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasViewport;
10302 g.NextWindowData.ViewportId = id;
10305void ImGui::SetNextWindowDockID(ImGuiID
id, ImGuiCond cond)
10308 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasDock;
10309 g.NextWindowData.DockCond = cond ? cond : ImGuiCond_Always;
10310 g.NextWindowData.DockId = id;
10316 IM_ASSERT((window_class->ViewportFlagsOverrideSet & window_class->ViewportFlagsOverrideClear) ==
10318 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasWindowClass;
10319 g.NextWindowData.WindowClass = *window_class;
10323void ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags)
10326 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasRefreshPolicy;
10327 g.NextWindowData.RefreshFlagsVal = flags;
10333 return window->DrawList;
10336float ImGui::GetWindowDpiScale()
10339 return g.CurrentDpiScale;
10345 IM_ASSERT(g.CurrentViewport != NULL && g.CurrentViewport == g.CurrentWindow->Viewport);
10346 return g.CurrentViewport;
10351 return GImGui->Font;
10354float ImGui::GetFontSize()
10356 return GImGui->FontSize;
10359ImVec2 ImGui::GetFontTexUvWhitePixel()
10361 return GImGui->DrawListSharedData.TexUvWhitePixel;
10364void ImGui::SetWindowFontScale(
float scale)
10366 IM_ASSERT(scale > 0.0f);
10369 window->FontWindowScale = scale;
10370 g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
10371 g.FontScale = g.DrawListSharedData.FontScale = g.FontSize / g.Font->FontSize;
10374void ImGui::PushFocusScope(ImGuiID
id)
10379 data.WindowID = g.CurrentWindow->ID;
10380 g.FocusScopeStack.push_back(data);
10381 g.CurrentFocusScopeId = id;
10384void ImGui::PopFocusScope()
10387 if (g.FocusScopeStack.Size <= g.StackSizesInBeginForCurrentWindow->SizeOfFocusScopeStack)
10389 IM_ASSERT_USER_ERROR(0,
"Calling PopFocusScope() too many times!");
10392 g.FocusScopeStack.pop_back();
10393 g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().ID : 0;
10396void ImGui::SetNavFocusScope(ImGuiID focus_scope_id)
10399 g.NavFocusScopeId = focus_scope_id;
10400 g.NavFocusRoute.resize(0);
10401 if (focus_scope_id == 0)
10403 IM_ASSERT(g.NavWindow != NULL);
10406 if (focus_scope_id == g.CurrentFocusScopeId)
10409 for (
int n = g.FocusScopeStack.Size - 1; n >= 0 && g.FocusScopeStack.Data[n].WindowID == g.CurrentWindow->ID;
10411 g.NavFocusRoute.push_back(g.FocusScopeStack.Data[n]);
10413 else if (focus_scope_id == g.NavWindow->NavRootFocusScopeId)
10414 g.NavFocusRoute.push_back({focus_scope_id, g.NavWindow->ID});
10419 for (
ImGuiWindow *window = g.NavWindow->ParentWindowForFocusRoute; window != NULL;
10420 window = window->ParentWindowForFocusRoute)
10421 g.NavFocusRoute.push_back({window->NavRootFocusScopeId, window->ID});
10422 IM_ASSERT(g.NavFocusRoute.Size < 100);
10426void ImGui::FocusItem()
10430 IMGUI_DEBUG_LOG_FOCUS(
"FocusItem(0x%08x) in window \"%s\"\n", g.LastItemData.ID, window->Name);
10431 if (g.DragDropActive || g.MovingWindow != NULL)
10433 IMGUI_DEBUG_LOG_FOCUS(
"FocusItem() ignored while DragDropActive!\n");
10437 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_FocusApi |
10438 ImGuiNavMoveFlags_NoSetNavCursorVisible | ImGuiNavMoveFlags_NoSelect;
10439 ImGuiScrollFlags scroll_flags = window->Appearing
10440 ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY
10441 : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
10442 SetNavWindow(window);
10443 NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_Up, move_flags, scroll_flags);
10444 NavMoveRequestResolveWithLastItem(&g.NavMoveResultLocal);
10447void ImGui::ActivateItemByID(ImGuiID
id)
10450 g.NavNextActivateId = id;
10451 g.NavNextActivateFlags = ImGuiActivateFlags_None;
10456void ImGui::SetKeyboardFocusHere(
int offset)
10460 IM_ASSERT(offset >= -1);
10461 IMGUI_DEBUG_LOG_FOCUS(
"SetKeyboardFocusHere(%d) in window \"%s\"\n", offset, window->Name);
10467 if (g.DragDropActive || g.MovingWindow != NULL)
10469 IMGUI_DEBUG_LOG_FOCUS(
"SetKeyboardFocusHere() ignored while DragDropActive!\n");
10473 SetNavWindow(window);
10475 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate |
10476 ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavCursorVisible;
10477 ImGuiScrollFlags scroll_flags = window->Appearing
10478 ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY
10479 : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
10480 NavMoveRequestSubmit(
10481 ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, move_flags,
10485 NavMoveRequestResolveWithLastItem(&g.NavMoveResultLocal);
10489 g.NavTabbingDir = 1;
10490 g.NavTabbingCounter = offset + 1;
10494void ImGui::SetItemDefaultFocus()
10498 if (!window->Appearing)
10500 if (g.NavWindow != window->RootWindowForNav || (!g.NavInitRequest && g.NavInitResult.ID == 0) ||
10501 g.NavLayer != window->DC.NavLayerCurrent)
10504 g.NavInitRequest =
false;
10505 NavApplyItemToResult(&g.NavInitResult);
10506 NavUpdateAnyRequestFlag();
10510 if (!window->ClipRect.Contains(g.LastItemData.Rect))
10511 ScrollToRectEx(window, g.LastItemData.Rect, ImGuiScrollFlags_None);
10517 window->DC.StateStorage = tree ? tree : &window->StateStorage;
10523 return window->DC.StateStorage;
10526bool ImGui::IsRectVisible(
const ImVec2 &size)
10529 return window->ClipRect.Overlaps(
ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
10532bool ImGui::IsRectVisible(
const ImVec2 &rect_min,
const ImVec2 &rect_max)
10535 return window->ClipRect.Overlaps(
ImRect(rect_min, rect_max));
10544IM_MSVC_RUNTIME_CHECKS_OFF
10545ImGuiID ImGuiWindow::GetID(
const char *str,
const char *str_end)
10547 ImGuiID seed = IDStack.back();
10548 ImGuiID
id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
10549#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10551 if (g.DebugHookIdInfo ==
id)
10552 ImGui::DebugHookIdInfo(
id, ImGuiDataType_String, str, str_end);
10557ImGuiID ImGuiWindow::GetID(
const void *ptr)
10559 ImGuiID seed = IDStack.back();
10560 ImGuiID
id = ImHashData(&ptr,
sizeof(
void *), seed);
10561#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10563 if (g.DebugHookIdInfo ==
id)
10564 ImGui::DebugHookIdInfo(
id, ImGuiDataType_Pointer, ptr, NULL);
10569ImGuiID ImGuiWindow::GetID(
int n)
10571 ImGuiID seed = IDStack.back();
10572 ImGuiID
id = ImHashData(&n,
sizeof(n), seed);
10573#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10575 if (g.DebugHookIdInfo ==
id)
10576 ImGui::DebugHookIdInfo(
id, ImGuiDataType_S32, (
void *)(intptr_t)n, NULL);
10583ImGuiID ImGuiWindow::GetIDFromPos(
const ImVec2 &p_abs)
10585 ImGuiID seed = IDStack.back();
10586 ImVec2 p_rel = ImGui::WindowPosAbsToRel(
this, p_abs);
10587 ImGuiID
id = ImHashData(&p_rel,
sizeof(p_rel), seed);
10592ImGuiID ImGuiWindow::GetIDFromRectangle(
const ImRect &r_abs)
10594 ImGuiID seed = IDStack.back();
10595 ImRect r_rel = ImGui::WindowRectAbsToRel(
this, r_abs);
10596 ImGuiID
id = ImHashData(&r_rel,
sizeof(r_rel), seed);
10600void ImGui::PushID(
const char *str_id)
10604 ImGuiID
id = window->GetID(str_id);
10605 window->IDStack.push_back(
id);
10608void ImGui::PushID(
const char *str_id_begin,
const char *str_id_end)
10612 ImGuiID
id = window->GetID(str_id_begin, str_id_end);
10613 window->IDStack.push_back(
id);
10616void ImGui::PushID(
const void *ptr_id)
10620 ImGuiID
id = window->GetID(ptr_id);
10621 window->IDStack.push_back(
id);
10624void ImGui::PushID(
int int_id)
10628 ImGuiID
id = window->GetID(int_id);
10629 window->IDStack.push_back(
id);
10633void ImGui::PushOverrideID(ImGuiID
id)
10637#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10638 if (g.DebugHookIdInfo ==
id)
10639 DebugHookIdInfo(
id, ImGuiDataType_ID, NULL, NULL);
10641 window->IDStack.push_back(
id);
10648ImGuiID ImGui::GetIDWithSeed(
const char *str,
const char *str_end, ImGuiID seed)
10650 ImGuiID
id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
10651#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10653 if (g.DebugHookIdInfo ==
id)
10654 DebugHookIdInfo(
id, ImGuiDataType_String, str, str_end);
10659ImGuiID ImGui::GetIDWithSeed(
int n, ImGuiID seed)
10661 ImGuiID
id = ImHashData(&n,
sizeof(n), seed);
10662#ifndef IMGUI_DISABLE_DEBUG_TOOLS
10664 if (g.DebugHookIdInfo ==
id)
10665 DebugHookIdInfo(
id, ImGuiDataType_S32, (
void *)(intptr_t)n, NULL);
10673 if (window->IDStack.Size <= 1)
10675 IM_ASSERT_USER_ERROR(0,
"Calling PopID() too many times!");
10678 window->IDStack.pop_back();
10681ImGuiID ImGui::GetID(
const char *str_id)
10684 return window->GetID(str_id);
10687ImGuiID ImGui::GetID(
const char *str_id_begin,
const char *str_id_end)
10690 return window->GetID(str_id_begin, str_id_end);
10693ImGuiID ImGui::GetID(
const void *ptr_id)
10696 return window->GetID(ptr_id);
10699ImGuiID ImGui::GetID(
int int_id)
10702 return window->GetID(int_id);
10704IM_MSVC_RUNTIME_CHECKS_RESTORE
10772static ImGuiKeyChord GetModForLRModKey(ImGuiKey key)
10774 if (key == ImGuiKey_LeftCtrl || key == ImGuiKey_RightCtrl)
10775 return ImGuiMod_Ctrl;
10776 if (key == ImGuiKey_LeftShift || key == ImGuiKey_RightShift)
10777 return ImGuiMod_Shift;
10778 if (key == ImGuiKey_LeftAlt || key == ImGuiKey_RightAlt)
10779 return ImGuiMod_Alt;
10780 if (key == ImGuiKey_LeftSuper || key == ImGuiKey_RightSuper)
10781 return ImGuiMod_Super;
10782 return ImGuiMod_None;
10785ImGuiKeyChord ImGui::FixupKeyChord(ImGuiKeyChord key_chord)
10788 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
10789 if (IsLRModKey(key))
10790 key_chord |= GetModForLRModKey(key);
10799 if (key & ImGuiMod_Mask_)
10800 key = ConvertSingleModFlagToKey(key);
10802 IM_ASSERT(IsNamedKey(key) &&
10803 "Support for user key indices was dropped in favor of ImGuiKey. Please update backend & user code.");
10804 return &g.IO.KeysData[key - ImGuiKey_NamedKey_BEGIN];
10808static const char *
const GKeyNames[] = {
10932 "GamepadFaceRight",
10936 "GamepadDpadRight",
10945 "GamepadLStickLeft",
10946 "GamepadLStickRight",
10948 "GamepadLStickDown",
10949 "GamepadRStickLeft",
10950 "GamepadRStickRight",
10952 "GamepadRStickDown",
10965IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames));
10967const char *ImGui::GetKeyName(ImGuiKey key)
10969 if (key == ImGuiKey_None)
10971 IM_ASSERT(IsNamedKeyOrMod(key) &&
10972 "Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
10973 if (key & ImGuiMod_Mask_)
10974 key = ConvertSingleModFlagToKey(key);
10975 if (!IsNamedKey(key))
10978 return GKeyNames[key - ImGuiKey_NamedKey_BEGIN];
10983const char *ImGui::GetKeyChordName(ImGuiKeyChord key_chord)
10987 const ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
10988 if (IsLRModKey(key))
10989 key_chord &= ~GetModForLRModKey(key);
10990 ImFormatString(g.TempKeychordName, IM_ARRAYSIZE(g.TempKeychordName),
"%s%s%s%s%s",
10991 (key_chord & ImGuiMod_Ctrl) ?
"Ctrl+" :
"", (key_chord & ImGuiMod_Shift) ?
"Shift+" :
"",
10992 (key_chord & ImGuiMod_Alt) ?
"Alt+" :
"", (key_chord & ImGuiMod_Super) ?
"Super+" :
"",
10993 (key != ImGuiKey_None || key_chord == ImGuiKey_None) ? GetKeyName(key) :
"");
10995 if (key == ImGuiKey_None && key_chord != 0)
10996 if ((len = ImStrlen(g.TempKeychordName)) != 0)
10997 g.TempKeychordName[len - 1] = 0;
10998 return g.TempKeychordName;
11005int ImGui::CalcTypematicRepeatAmount(
float t0,
float t1,
float repeat_delay,
float repeat_rate)
11011 if (repeat_rate <= 0.0f)
11012 return (t0 < repeat_delay) && (t1 >= repeat_delay);
11013 const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate);
11014 const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate);
11015 const int count = count_t1 - count_t0;
11019void ImGui::GetTypematicRepeatRate(ImGuiInputFlags flags,
float *repeat_delay,
float *repeat_rate)
11022 switch (flags & ImGuiInputFlags_RepeatRateMask_)
11024 case ImGuiInputFlags_RepeatRateNavMove:
11025 *repeat_delay = g.IO.KeyRepeatDelay * 0.72f;
11026 *repeat_rate = g.IO.KeyRepeatRate * 0.80f;
11028 case ImGuiInputFlags_RepeatRateNavTweak:
11029 *repeat_delay = g.IO.KeyRepeatDelay * 0.72f;
11030 *repeat_rate = g.IO.KeyRepeatRate * 0.30f;
11032 case ImGuiInputFlags_RepeatRateDefault:
11034 *repeat_delay = g.IO.KeyRepeatDelay * 1.00f;
11035 *repeat_rate = g.IO.KeyRepeatRate * 1.00f;
11043int ImGui::GetKeyPressedAmount(ImGuiKey key,
float repeat_delay,
float repeat_rate)
11047 if (!key_data->Down)
11050 const float t = key_data->DownDuration;
11051 return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat_rate);
11056ImVec2 ImGui::GetKeyMagnitude2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down)
11058 return ImVec2(GetKeyData(key_right)->AnalogValue - GetKeyData(key_left)->AnalogValue,
11059 GetKeyData(key_down)->AnalogValue - GetKeyData(key_up)->AnalogValue);
11069 rt->EntriesNext.resize(0);
11070 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
11072 const int new_routing_start_idx = rt->EntriesNext.Size;
11074 for (
int old_routing_idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; old_routing_idx != -1;
11075 old_routing_idx = routing_entry->NextEntryIndex)
11077 routing_entry = &rt->Entries[old_routing_idx];
11078 routing_entry->RoutingCurrScore = routing_entry->RoutingNextScore;
11079 routing_entry->RoutingCurr = routing_entry->RoutingNext;
11080 routing_entry->RoutingNext = ImGuiKeyOwner_NoOwner;
11081 routing_entry->RoutingNextScore = 255;
11082 if (routing_entry->RoutingCurr == ImGuiKeyOwner_NoOwner)
11084 rt->EntriesNext.push_back(*routing_entry);
11088 if (routing_entry->Mods == g.IO.KeyMods)
11091 if (owner_data->OwnerCurr == ImGuiKeyOwner_NoOwner)
11093 owner_data->OwnerCurr = routing_entry->RoutingCurr;
11101 rt->Index[key - ImGuiKey_NamedKey_BEGIN] =
11102 (ImGuiKeyRoutingIndex)(new_routing_start_idx < rt->EntriesNext.Size ? new_routing_start_idx : -1);
11103 for (
int n = new_routing_start_idx; n < rt->EntriesNext.Size; n++)
11104 rt->EntriesNext[n].NextEntryIndex = (ImGuiKeyRoutingIndex)((n + 1 < rt->EntriesNext.Size) ? n + 1 : -1);
11106 rt->Entries.swap(rt->EntriesNext);
11110static inline ImGuiID GetRoutingIdFromOwnerId(ImGuiID owner_id)
11113 return (owner_id != ImGuiKeyOwner_NoOwner && owner_id != ImGuiKeyOwner_Any) ? owner_id : g.CurrentFocusScopeId;
11127 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
11128 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
11129 if (key == ImGuiKey_None)
11130 key = ConvertSingleModFlagToKey(mods);
11131 IM_ASSERT(IsNamedKey(key));
11135 for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1;
11136 idx = routing_data->NextEntryIndex)
11138 routing_data = &rt->Entries[idx];
11139 if (routing_data->Mods == mods)
11140 return routing_data;
11144 ImGuiKeyRoutingIndex routing_data_idx = (ImGuiKeyRoutingIndex)rt->Entries.Size;
11146 routing_data = &rt->Entries[routing_data_idx];
11147 routing_data->Mods = (ImU16)mods;
11148 routing_data->NextEntryIndex = rt->Index[key - ImGuiKey_NamedKey_BEGIN];
11149 rt->Index[key - ImGuiKey_NamedKey_BEGIN] = routing_data_idx;
11150 return routing_data;
11161static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags)
11164 if (flags & ImGuiInputFlags_RouteFocused)
11169 if (owner_id != 0 && g.ActiveId == owner_id)
11179 if (focus_scope_id == 0)
11181 for (
int index_in_focus_path = 0; index_in_focus_path < g.NavFocusRoute.Size; index_in_focus_path++)
11182 if (g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id)
11183 return 3 + index_in_focus_path;
11186 else if (flags & ImGuiInputFlags_RouteActive)
11188 if (owner_id != 0 && g.ActiveId == owner_id)
11192 else if (flags & ImGuiInputFlags_RouteGlobal)
11194 if (flags & ImGuiInputFlags_RouteOverActive)
11196 if (flags & ImGuiInputFlags_RouteOverFocused)
11208static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord)
11214 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
11215 const bool ignore_char_inputs =
11216 ((mods & ImGuiMod_Ctrl) && !(mods & ImGuiMod_Alt)) || (g.IO.ConfigMacOSXBehaviors && (mods & ImGuiMod_Ctrl));
11217 if (ignore_char_inputs)
11221 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
11222 if (key == ImGuiKey_None)
11224 return g.KeysMayBeCharInput.TestBit(key);
11232bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)
11235 if ((flags & ImGuiInputFlags_RouteTypeMask_) == 0)
11236 flags |= ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused |
11237 ImGuiInputFlags_RouteOverActive;
11240 IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_));
11241 IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_NoOwner);
11243 (ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused))
11244 IM_ASSERT(flags & ImGuiInputFlags_RouteGlobal);
11247 key_chord = FixupKeyChord(key_chord);
11250 if (g.DebugBreakInShortcutRouting == key_chord)
11253 if (flags & ImGuiInputFlags_RouteUnlessBgFocused)
11254 if (g.NavWindow == NULL)
11258 if (flags & ImGuiInputFlags_RouteAlways)
11260 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> always, no register\n",
11261 GetKeyChordName(key_chord), flags, owner_id);
11266 if (g.ActiveId != 0 && g.ActiveId != owner_id)
11268 if (flags & ImGuiInputFlags_RouteActive)
11277 if (g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord))
11279 IMGUI_DEBUG_LOG_INPUTROUTING(
11280 "SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> filtered as potential char input\n",
11281 GetKeyChordName(key_chord), flags, owner_id);
11286 if ((flags & ImGuiInputFlags_RouteOverActive) == 0 && g.ActiveIdUsingAllKeyboardKeys)
11288 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
11289 if (key == ImGuiKey_None)
11290 key = ConvertSingleModFlagToKey((ImGuiKey)(key_chord & ImGuiMod_Mask_));
11291 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
11297 ImGuiID focus_scope_id = g.CurrentFocusScopeId;
11298 if (flags & ImGuiInputFlags_RouteFromRootWindow)
11299 focus_scope_id = g.CurrentWindow->RootWindow->ID;
11301 const int score = CalcRoutingScore(focus_scope_id, owner_id, flags);
11302 IMGUI_DEBUG_LOG_INPUTROUTING(
"SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> score %d\n",
11303 GetKeyChordName(key_chord), flags, owner_id, score);
11312 if (score < routing_data->RoutingNextScore)
11314 routing_data->RoutingNext = owner_id;
11315 routing_data->RoutingNextScore = (ImU8)score;
11319 if (routing_data->RoutingCurr == owner_id)
11320 IMGUI_DEBUG_LOG_INPUTROUTING(
"--> granting current route\n");
11321 return routing_data->RoutingCurr == owner_id;
11327bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id)
11329 const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id);
11330 key_chord = FixupKeyChord(key_chord);
11332 return routing_data->RoutingCurr == routing_id;
11337bool ImGui::IsKeyDown(ImGuiKey key)
11339 return IsKeyDown(key, ImGuiKeyOwner_Any);
11342bool ImGui::IsKeyDown(ImGuiKey key, ImGuiID owner_id)
11345 if (!key_data->Down)
11347 if (!TestKeyOwner(key, owner_id))
11352bool ImGui::IsKeyPressed(ImGuiKey key,
bool repeat)
11354 return IsKeyPressed(key, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
11359bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiInputFlags flags, ImGuiID owner_id)
11362 if (!key_data->Down)
11365 const float t = key_data->DownDuration;
11368 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0);
11369 if (flags & (ImGuiInputFlags_RepeatRateMask_ |
11370 ImGuiInputFlags_RepeatUntilMask_))
11371 flags |= ImGuiInputFlags_Repeat;
11373 bool pressed = (t == 0.0f);
11374 if (!pressed && (flags & ImGuiInputFlags_Repeat) != 0)
11376 float repeat_delay, repeat_rate;
11377 GetTypematicRepeatRate(flags, &repeat_delay, &repeat_rate);
11378 pressed = (t > repeat_delay) && GetKeyPressedAmount(key, repeat_delay, repeat_rate) > 0;
11379 if (pressed && (flags & ImGuiInputFlags_RepeatUntilMask_))
11385 double key_pressed_time = g.Time - t + 0.00001f;
11386 if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChange) && (g.LastKeyModsChangeTime > key_pressed_time))
11388 if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone) &&
11389 (g.LastKeyModsChangeFromNoneTime > key_pressed_time))
11391 if ((flags & ImGuiInputFlags_RepeatUntilOtherKeyPress) && (g.LastKeyboardKeyPressTime > key_pressed_time))
11397 if (!TestKeyOwner(key, owner_id))
11402bool ImGui::IsKeyReleased(ImGuiKey key)
11407bool ImGui::IsKeyReleased(ImGuiKey key, ImGuiID owner_id)
11410 if (key_data->DownDurationPrev < 0.0f || key_data->Down)
11412 if (!TestKeyOwner(key, owner_id))
11417bool ImGui::IsMouseDown(ImGuiMouseButton button)
11420 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11421 return g.IO.MouseDown[button] &&
11422 TestKeyOwner(MouseButtonToKey(button),
11423 ImGuiKeyOwner_Any);
11427bool ImGui::IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id)
11430 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11431 return g.IO.MouseDown[button] &&
11432 TestKeyOwner(MouseButtonToKey(button),
11437bool ImGui::IsMouseClicked(ImGuiMouseButton button,
bool repeat)
11439 return IsMouseClicked(button, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
11442bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id)
11445 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11446 if (!g.IO.MouseDown[button])
11449 const float t = g.IO.MouseDownDuration[button];
11452 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsMouseClicked) ==
11456 const bool repeat = (flags & ImGuiInputFlags_Repeat) != 0;
11457 const bool pressed =
11458 (t == 0.0f) || (repeat && t > g.IO.KeyRepeatDelay &&
11459 CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0);
11463 if (!TestKeyOwner(MouseButtonToKey(button), owner_id))
11469bool ImGui::IsMouseReleased(ImGuiMouseButton button)
11472 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11473 return g.IO.MouseReleased[button] &&
11475 MouseButtonToKey(button),
11476 ImGuiKeyOwner_Any);
11479bool ImGui::IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id)
11482 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11483 return g.IO.MouseReleased[button] &&
11484 TestKeyOwner(MouseButtonToKey(button),
11491bool ImGui::IsMouseReleasedWithDelay(ImGuiMouseButton button,
float delay)
11494 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11495 const float time_since_release = (float)(g.Time - g.IO.MouseReleasedTime[button]);
11496 return !IsMouseDown(button) && (time_since_release - g.IO.DeltaTime < delay) && (time_since_release >= delay);
11499bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
11502 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11503 return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any);
11506bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button, ImGuiID owner_id)
11509 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11510 return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), owner_id);
11513int ImGui::GetMouseClickedCount(ImGuiMouseButton button)
11516 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11517 return g.IO.MouseClickedCount[button];
11523bool ImGui::IsMouseHoveringRect(
const ImVec2 &r_min,
const ImVec2 &r_max,
bool clip)
11528 ImRect rect_clipped(r_min, r_max);
11530 rect_clipped.ClipWith(g.CurrentWindow->ClipRect);
11533 if (!rect_clipped.ContainsWithPad(g.IO.MousePos, g.Style.TouchExtraPadding))
11535 if (!g.MouseViewport->GetMainRect().Overlaps(rect_clipped))
11542bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button,
float lock_threshold)
11545 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11546 if (lock_threshold < 0.0f)
11547 lock_threshold = g.IO.MouseDragThreshold;
11548 return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
11551bool ImGui::IsMouseDragging(ImGuiMouseButton button,
float lock_threshold)
11554 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11555 if (!g.IO.MouseDown[button])
11557 return IsMouseDragPastThreshold(button, lock_threshold);
11560ImVec2 ImGui::GetMousePos()
11563 return g.IO.MousePos;
11569void ImGui::TeleportMousePos(
const ImVec2 &pos)
11572 g.IO.MousePos = g.IO.MousePosPrev = pos;
11573 g.IO.MouseDelta =
ImVec2(0.0f, 0.0f);
11574 g.IO.WantSetMousePos =
true;
11580ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
11583 if (g.BeginPopupStack.Size > 0)
11584 return g.OpenPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos;
11585 return g.IO.MousePos;
11589bool ImGui::IsMousePosValid(
const ImVec2 *mouse_pos)
11594 IM_ASSERT(GImGui != NULL);
11595 const float MOUSE_INVALID = -256000.0f;
11596 ImVec2 p = mouse_pos ? *mouse_pos : GImGui->IO.MousePos;
11597 return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID;
11602bool ImGui::IsAnyMouseDown()
11605 for (
int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++)
11606 if (g.IO.MouseDown[n])
11615ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button,
float lock_threshold)
11618 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11619 if (lock_threshold < 0.0f)
11620 lock_threshold = g.IO.MouseDragThreshold;
11621 if (g.IO.MouseDown[button] || g.IO.MouseReleased[button])
11622 if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
11623 if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MouseClickedPos[button]))
11624 return g.IO.MousePos - g.IO.MouseClickedPos[button];
11625 return ImVec2(0.0f, 0.0f);
11628void ImGui::ResetMouseDragDelta(ImGuiMouseButton button)
11631 IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
11633 g.IO.MouseClickedPos[button] = g.IO.MousePos;
11640ImGuiMouseCursor ImGui::GetMouseCursor()
11643 return g.MouseCursor;
11650void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
11653 g.MouseCursor = cursor_type;
11656static void UpdateAliasKey(ImGuiKey key,
bool v,
float analog_value)
11658 IM_ASSERT(ImGui::IsAliasKey(key));
11660 key_data->Down = v;
11661 key_data->AnalogValue = analog_value;
11665static ImGuiKeyChord GetMergedModsFromKeys()
11667 ImGuiKeyChord mods = 0;
11668 if (ImGui::IsKeyDown(ImGuiMod_Ctrl))
11670 mods |= ImGuiMod_Ctrl;
11672 if (ImGui::IsKeyDown(ImGuiMod_Shift))
11674 mods |= ImGuiMod_Shift;
11676 if (ImGui::IsKeyDown(ImGuiMod_Alt))
11678 mods |= ImGuiMod_Alt;
11680 if (ImGui::IsKeyDown(ImGuiMod_Super))
11682 mods |= ImGuiMod_Super;
11687static void ImGui::UpdateKeyboardInputs()
11692 if (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard)
11693 io.ClearInputKeys();
11696 for (
int n = 0; n < ImGuiMouseButton_COUNT; n++)
11697 UpdateAliasKey(MouseButtonToKey(n), io.MouseDown[n], io.MouseDown[n] ? 1.0f : 0.0f);
11698 UpdateAliasKey(ImGuiKey_MouseWheelX, io.MouseWheelH != 0.0f, io.MouseWheelH);
11699 UpdateAliasKey(ImGuiKey_MouseWheelY, io.MouseWheel != 0.0f, io.MouseWheel);
11707 const ImGuiKeyChord prev_key_mods = io.KeyMods;
11708 io.KeyMods = GetMergedModsFromKeys();
11709 io.KeyCtrl = (io.KeyMods & ImGuiMod_Ctrl) != 0;
11710 io.KeyShift = (io.KeyMods & ImGuiMod_Shift) != 0;
11711 io.KeyAlt = (io.KeyMods & ImGuiMod_Alt) != 0;
11712 io.KeySuper = (io.KeyMods & ImGuiMod_Super) != 0;
11713 if (prev_key_mods != io.KeyMods)
11714 g.LastKeyModsChangeTime = g.Time;
11715 if (prev_key_mods != io.KeyMods && prev_key_mods == 0)
11716 g.LastKeyModsChangeFromNoneTime = g.Time;
11719 if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0)
11720 for (
int key = ImGuiKey_Gamepad_BEGIN; key < ImGuiKey_Gamepad_END; key++)
11722 io.KeysData[key - ImGuiKey_NamedKey_BEGIN].Down =
false;
11723 io.KeysData[key - ImGuiKey_NamedKey_BEGIN].AnalogValue = 0.0f;
11727 for (
int key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key++)
11729 ImGuiKeyData *key_data = &io.KeysData[key - ImGuiKey_NamedKey_BEGIN];
11730 key_data->DownDurationPrev = key_data->DownDuration;
11731 key_data->DownDuration =
11732 key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f;
11733 if (key_data->DownDuration == 0.0f)
11735 if (IsKeyboardKey((ImGuiKey)key))
11736 g.LastKeyboardKeyPressTime = g.Time;
11737 else if (key == ImGuiKey_ReservedForModCtrl || key == ImGuiKey_ReservedForModShift ||
11738 key == ImGuiKey_ReservedForModAlt || key == ImGuiKey_ReservedForModSuper)
11739 g.LastKeyboardKeyPressTime = g.Time;
11744 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
11746 ImGuiKeyData *key_data = &io.KeysData[key - ImGuiKey_NamedKey_BEGIN];
11747 ImGuiKeyOwnerData *owner_data = &g.KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN];
11748 owner_data->OwnerCurr = owner_data->OwnerNext;
11749 if (!key_data->Down)
11751 owner_data->OwnerNext = ImGuiKeyOwner_NoOwner;
11752 owner_data->LockThisFrame = owner_data->LockUntilRelease =
11753 owner_data->LockUntilRelease && key_data->Down;
11757 UpdateKeyRoutingTable(&g.KeysRoutingTable);
11760static void ImGui::UpdateMouseInputs()
11772 io.MouseWheelRequestAxisSwap = io.KeyShift && !io.ConfigMacOSXBehaviors;
11775 if (IsMousePosValid(&io.MousePos))
11776 io.MousePos = g.MouseLastValidPos = ImFloor(io.MousePos);
11780 if (IsMousePosValid(&io.MousePos) && IsMousePosValid(&io.MousePosPrev))
11781 io.MouseDelta = io.MousePos - io.MousePosPrev;
11783 io.MouseDelta =
ImVec2(0.0f, 0.0f);
11788 const float mouse_stationary_threshold =
11789 (io.MouseSource == ImGuiMouseSource_Mouse)
11792 const bool mouse_stationary =
11793 (ImLengthSqr(io.MouseDelta) <= mouse_stationary_threshold * mouse_stationary_threshold);
11794 g.MouseStationaryTimer = mouse_stationary ? (g.MouseStationaryTimer + io.DeltaTime) : 0.0f;
11799 if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
11800 g.NavHighlightItemUnderNav =
false;
11802 for (
int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
11804 io.MouseClicked[i] = io.MouseDown[i] && io.MouseDownDuration[i] < 0.0f;
11805 io.MouseClickedCount[i] = 0;
11806 io.MouseReleased[i] = !io.MouseDown[i] && io.MouseDownDuration[i] >= 0.0f;
11807 if (io.MouseReleased[i])
11808 io.MouseReleasedTime[i] = g.Time;
11809 io.MouseDownDurationPrev[i] = io.MouseDownDuration[i];
11810 io.MouseDownDuration[i] =
11811 io.MouseDown[i] ? (io.MouseDownDuration[i] < 0.0f ? 0.0f : io.MouseDownDuration[i] + io.DeltaTime) : -1.0f;
11812 if (io.MouseClicked[i])
11814 bool is_repeated_click =
false;
11815 if ((
float)(g.Time - io.MouseClickedTime[i]) < io.MouseDoubleClickTime)
11817 ImVec2 delta_from_click_pos =
11818 IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) :
ImVec2(0.0f, 0.0f);
11819 if (ImLengthSqr(delta_from_click_pos) < io.MouseDoubleClickMaxDist * io.MouseDoubleClickMaxDist)
11820 is_repeated_click =
true;
11822 if (is_repeated_click)
11823 io.MouseClickedLastCount[i]++;
11825 io.MouseClickedLastCount[i] = 1;
11826 io.MouseClickedTime[i] = g.Time;
11827 io.MouseClickedPos[i] = io.MousePos;
11828 io.MouseClickedCount[i] = io.MouseClickedLastCount[i];
11829 io.MouseDragMaxDistanceAbs[i] =
ImVec2(0.0f, 0.0f);
11830 io.MouseDragMaxDistanceSqr[i] = 0.0f;
11832 else if (io.MouseDown[i])
11836 ImVec2 delta_from_click_pos =
11837 IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) :
ImVec2(0.0f, 0.0f);
11838 io.MouseDragMaxDistanceSqr[i] = ImMax(io.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos));
11839 io.MouseDragMaxDistanceAbs[i].x =
11840 ImMax(io.MouseDragMaxDistanceAbs[i].x,
11841 delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_click_pos.x);
11842 io.MouseDragMaxDistanceAbs[i].y =
11843 ImMax(io.MouseDragMaxDistanceAbs[i].y,
11844 delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_click_pos.y);
11848 io.MouseDoubleClicked[i] = (io.MouseClickedCount[i] == 2);
11852 if (io.MouseClicked[i])
11853 g.NavHighlightItemUnderNav =
false;
11857static void LockWheelingWindow(
ImGuiWindow *window,
float wheel_amount)
11861 g.WheelingWindowReleaseTimer =
11862 ImMin(g.WheelingWindowReleaseTimer + ImAbs(wheel_amount) * WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER,
11863 WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER);
11865 g.WheelingWindowReleaseTimer = 0.0f;
11866 if (g.WheelingWindow == window)
11868 IMGUI_DEBUG_LOG_IO(
"[io] LockWheelingWindow() \"%s\"\n", window ? window->Name :
"NULL");
11869 g.WheelingWindow = window;
11870 g.WheelingWindowRefMousePos = g.IO.MousePos;
11871 if (window == NULL)
11873 g.WheelingWindowStartFrame = -1;
11874 g.WheelingAxisAvg =
ImVec2(0.0f, 0.0f);
11883 for (
int axis = 0; axis < 2; axis++)
11884 if (wheel[axis] != 0.0f)
11885 for (
ImGuiWindow *window = windows[axis] = g.HoveredWindow; window->Flags & ImGuiWindowFlags_ChildWindow;
11886 window = windows[axis] = window->ParentWindow)
11893 const bool has_scrolling = (window->ScrollMax[axis] != 0.0f);
11894 const bool inputs_disabled = (window->Flags & ImGuiWindowFlags_NoScrollWithMouse) &&
11895 !(window->Flags & ImGuiWindowFlags_NoMouseInputs);
11898 if (has_scrolling && !inputs_disabled)
11901 if (windows[0] == NULL && windows[1] == NULL)
11905 if (windows[0] == windows[1] || windows[0] == NULL || windows[1] == NULL)
11906 return windows[1] ? windows[1] : windows[0];
11911 if (g.WheelingWindowStartFrame == -1)
11912 g.WheelingWindowStartFrame = g.FrameCount;
11913 if ((g.WheelingWindowStartFrame == g.FrameCount && wheel.x != 0.0f && wheel.y != 0.0f) ||
11914 (g.WheelingAxisAvg.x == g.WheelingAxisAvg.y))
11916 g.WheelingWindowWheelRemainder = wheel;
11919 return (g.WheelingAxisAvg.x > g.WheelingAxisAvg.y) ? windows[0] : windows[1];
11923void ImGui::UpdateMouseWheel()
11929 if (g.WheelingWindow != NULL)
11931 g.WheelingWindowReleaseTimer -= g.IO.DeltaTime;
11932 if (IsMousePosValid() && ImLengthSqr(g.IO.MousePos - g.WheelingWindowRefMousePos) >
11933 g.IO.MouseDragThreshold * g.IO.MouseDragThreshold)
11934 g.WheelingWindowReleaseTimer = 0.0f;
11935 if (g.WheelingWindowReleaseTimer <= 0.0f)
11936 LockWheelingWindow(NULL, 0.0f);
11940 wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, ImGuiKeyOwner_NoOwner) ? g.IO.MouseWheelH : 0.0f;
11941 wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, ImGuiKeyOwner_NoOwner) ? g.IO.MouseWheel : 0.0f;
11944 ImGuiWindow *mouse_window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow;
11945 if (!mouse_window || mouse_window->Collapsed)
11951 if (wheel.y != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
11953 LockWheelingWindow(mouse_window, wheel.y);
11955 const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
11956 const float scale = new_font_scale / window->FontWindowScale;
11957 window->FontWindowScale = new_font_scale;
11958 if (window == window->RootWindow)
11960 const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
11961 SetWindowPos(window, window->Pos + offset, 0);
11962 window->Size = ImTrunc(window->Size * scale);
11963 window->SizeFull = ImTrunc(window->SizeFull * scale);
11972 if (g.IO.MouseWheelRequestAxisSwap)
11973 wheel =
ImVec2(wheel.y, 0.0f);
11977 g.WheelingAxisAvg.x = ImExponentialMovingAverage(g.WheelingAxisAvg.x, ImAbs(wheel.x), 30);
11978 g.WheelingAxisAvg.y = ImExponentialMovingAverage(g.WheelingAxisAvg.y, ImAbs(wheel.y), 30);
11982 wheel += g.WheelingWindowWheelRemainder;
11983 g.WheelingWindowWheelRemainder =
ImVec2(0.0f, 0.0f);
11984 if (wheel.x == 0.0f && wheel.y == 0.0f)
11990 if (
ImGuiWindow *window = (g.WheelingWindow ? g.WheelingWindow : FindBestWheelingWindow(wheel)))
11991 if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
11993 bool do_scroll[2] = {wheel.x != 0.0f && window->ScrollMax.x != 0.0f,
11994 wheel.y != 0.0f && window->ScrollMax.y != 0.0f};
11995 if (do_scroll[ImGuiAxis_X] && do_scroll[ImGuiAxis_Y])
11996 do_scroll[(g.WheelingAxisAvg.x > g.WheelingAxisAvg.y) ? ImGuiAxis_Y : ImGuiAxis_X] = false;
11997 if (do_scroll[ImGuiAxis_X])
11999 LockWheelingWindow(window, wheel.x);
12000 float max_step = window->InnerRect.GetWidth() * 0.67f;
12001 float scroll_step = ImTrunc(ImMin(2 * window->FontRefSize, max_step));
12002 SetScrollX(window, window->Scroll.x - wheel.x * scroll_step);
12003 g.WheelingWindowScrolledFrame = g.FrameCount;
12005 if (do_scroll[ImGuiAxis_Y])
12007 LockWheelingWindow(window, wheel.y);
12008 float max_step = window->InnerRect.GetHeight() * 0.67f;
12009 float scroll_step = ImTrunc(ImMin(5 * window->FontRefSize, max_step));
12010 SetScrollY(window, window->Scroll.y - wheel.y * scroll_step);
12011 g.WheelingWindowScrolledFrame = g.FrameCount;
12016void ImGui::SetNextFrameWantCaptureKeyboard(
bool want_capture_keyboard)
12019 g.WantCaptureKeyboardNextFrame = want_capture_keyboard ? 1 : 0;
12022void ImGui::SetNextFrameWantCaptureMouse(
bool want_capture_mouse)
12025 g.WantCaptureMouseNextFrame = want_capture_mouse ? 1 : 0;
12028#ifndef IMGUI_DISABLE_DEBUG_TOOLS
12029static const char *GetInputSourceName(ImGuiInputSource source)
12031 const char *input_source_names[] = {
"None",
"Mouse",
"Keyboard",
"Gamepad"};
12032 IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && source >= 0 &&
12033 source < ImGuiInputSource_COUNT);
12034 return input_source_names[source];
12036static const char *GetMouseSourceName(ImGuiMouseSource source)
12038 const char *mouse_source_names[] = {
"Mouse",
"TouchScreen",
"Pen"};
12039 IM_ASSERT(IM_ARRAYSIZE(mouse_source_names) == ImGuiMouseSource_COUNT && source >= 0 &&
12040 source < ImGuiMouseSource_COUNT);
12041 return mouse_source_names[source];
12043static void DebugPrintInputEvent(
const char *prefix,
const ImGuiInputEvent *e)
12046 if (e->Type == ImGuiInputEventType_MousePos)
12048 if (e->MousePos.PosX == -FLT_MAX && e->MousePos.PosY == -FLT_MAX)
12049 IMGUI_DEBUG_LOG_IO(
"[io] %s: MousePos (-FLT_MAX, -FLT_MAX)\n", prefix);
12051 IMGUI_DEBUG_LOG_IO(
"[io] %s: MousePos (%.1f, %.1f) (%s)\n", prefix, e->MousePos.PosX, e->MousePos.PosY,
12052 GetMouseSourceName(e->MousePos.MouseSource));
12055 if (e->Type == ImGuiInputEventType_MouseButton)
12057 IMGUI_DEBUG_LOG_IO(
"[io] %s: MouseButton %d %s (%s)\n", prefix, e->MouseButton.Button,
12058 e->MouseButton.Down ?
"Down" :
"Up", GetMouseSourceName(e->MouseButton.MouseSource));
12061 if (e->Type == ImGuiInputEventType_MouseWheel)
12063 IMGUI_DEBUG_LOG_IO(
"[io] %s: MouseWheel (%.3f, %.3f) (%s)\n", prefix, e->MouseWheel.WheelX,
12064 e->MouseWheel.WheelY, GetMouseSourceName(e->MouseWheel.MouseSource));
12067 if (e->Type == ImGuiInputEventType_MouseViewport)
12069 IMGUI_DEBUG_LOG_IO(
"[io] %s: MouseViewport (0x%08X)\n", prefix, e->MouseViewport.HoveredViewportID);
12072 if (e->Type == ImGuiInputEventType_Key)
12074 IMGUI_DEBUG_LOG_IO(
"[io] %s: Key \"%s\" %s\n", prefix, ImGui::GetKeyName(e->Key.Key),
12075 e->Key.Down ?
"Down" :
"Up");
12078 if (e->Type == ImGuiInputEventType_Text)
12080 IMGUI_DEBUG_LOG_IO(
"[io] %s: Text: %c (U+%08X)\n", prefix, e->Text.Char, e->Text.Char);
12083 if (e->Type == ImGuiInputEventType_Focus)
12085 IMGUI_DEBUG_LOG_IO(
"[io] %s: AppFocused %d\n", prefix, e->AppFocused.Focused);
12097void ImGui::UpdateInputEvents(
bool trickle_fast_inputs)
12106 const bool trickle_interleaved_nonchar_keys_and_text = (trickle_fast_inputs && g.WantTextInputNextFrame == 1);
12108 bool mouse_moved =
false, mouse_wheeled =
false, key_changed =
false, key_changed_nonchar =
false,
12109 text_inputted =
false;
12110 int mouse_button_changed = 0x00;
12114 for (; event_n < g.InputEventsQueue.Size; event_n++)
12117 if (e->Type == ImGuiInputEventType_MousePos)
12119 if (g.IO.WantSetMousePos)
12122 ImVec2 event_pos(e->MousePos.PosX, e->MousePos.PosY);
12123 if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputted))
12125 io.MousePos = event_pos;
12126 io.MouseSource = e->MousePos.MouseSource;
12127 mouse_moved =
true;
12129 else if (e->Type == ImGuiInputEventType_MouseButton)
12132 const ImGuiMouseButton button = e->MouseButton.Button;
12133 IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT);
12134 if (trickle_fast_inputs && ((mouse_button_changed & (1 << button)) || mouse_wheeled))
12136 if (trickle_fast_inputs && e->MouseButton.MouseSource == ImGuiMouseSource_TouchScreen &&
12139 io.MouseDown[button] = e->MouseButton.Down;
12140 io.MouseSource = e->MouseButton.MouseSource;
12141 mouse_button_changed |= (1 << button);
12143 else if (e->Type == ImGuiInputEventType_MouseWheel)
12146 if (trickle_fast_inputs && (mouse_moved || mouse_button_changed != 0))
12148 io.MouseWheelH += e->MouseWheel.WheelX;
12149 io.MouseWheel += e->MouseWheel.WheelY;
12150 io.MouseSource = e->MouseWheel.MouseSource;
12151 mouse_wheeled =
true;
12153 else if (e->Type == ImGuiInputEventType_MouseViewport)
12155 io.MouseHoveredViewport = e->MouseViewport.HoveredViewportID;
12157 else if (e->Type == ImGuiInputEventType_Key)
12160 if (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard)
12162 ImGuiKey key = e->Key.Key;
12163 IM_ASSERT(key != ImGuiKey_None);
12165 const int key_data_index = (int)(key_data - g.IO.KeysData);
12166 if (trickle_fast_inputs && key_data->Down != e->Key.Down &&
12167 (key_changed_mask.TestBit(key_data_index) || mouse_button_changed != 0))
12170 const bool key_is_potentially_for_char_input =
12171 IsKeyChordPotentiallyCharInput(GetMergedModsFromKeys() | key);
12172 if (trickle_interleaved_nonchar_keys_and_text && (text_inputted && !key_is_potentially_for_char_input))
12175 if (key_data->Down != e->Key.Down)
12178 key_changed =
true;
12179 key_changed_mask.SetBit(key_data_index);
12180 if (trickle_interleaved_nonchar_keys_and_text && !key_is_potentially_for_char_input)
12181 key_changed_nonchar =
true;
12184 key_data->Down = e->Key.Down;
12185 key_data->AnalogValue = e->Key.AnalogValue;
12187 else if (e->Type == ImGuiInputEventType_Text)
12189 if (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard)
12192 if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_moved || mouse_wheeled))
12194 if (trickle_interleaved_nonchar_keys_and_text && key_changed_nonchar)
12196 unsigned int c = e->Text.Char;
12197 io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c
12198 : IM_UNICODE_CODEPOINT_INVALID);
12199 if (trickle_interleaved_nonchar_keys_and_text)
12200 text_inputted =
true;
12202 else if (e->Type == ImGuiInputEventType_Focus)
12206 const bool focus_lost = !e->AppFocused.Focused;
12207 io.AppFocusLost = focus_lost;
12211 IM_ASSERT(0 &&
"Unknown event!");
12218 for (
int n = 0; n < event_n; n++)
12219 g.InputEventsTrail.push_back(g.InputEventsQueue[n]);
12222#ifndef IMGUI_DISABLE_DEBUG_TOOLS
12223 if (event_n != 0 && (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO))
12224 for (
int n = 0; n < g.InputEventsQueue.Size; n++)
12225 DebugPrintInputEvent(n < event_n ?
"Processed" :
"Remaining", &g.InputEventsQueue[n]);
12229 if (event_n == g.InputEventsQueue.Size)
12230 g.InputEventsQueue.resize(0);
12232 g.InputEventsQueue.erase(g.InputEventsQueue.Data, g.InputEventsQueue.Data + event_n);
12239 if (g.IO.AppFocusLost)
12241 g.IO.ClearInputKeys();
12242 g.IO.ClearInputMouse();
12246ImGuiID ImGui::GetKeyOwner(ImGuiKey key)
12248 if (!IsNamedKeyOrMod(key))
12249 return ImGuiKeyOwner_NoOwner;
12253 ImGuiID owner_id = owner_data->OwnerCurr;
12255 if (g.ActiveIdUsingAllKeyboardKeys && owner_id != g.ActiveId && owner_id != ImGuiKeyOwner_Any)
12256 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
12257 return ImGuiKeyOwner_NoOwner;
12267bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
12269 if (!IsNamedKeyOrMod(key))
12273 if (g.ActiveIdUsingAllKeyboardKeys && owner_id != g.ActiveId && owner_id != ImGuiKeyOwner_Any)
12274 if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
12278 if (owner_id == ImGuiKeyOwner_Any)
12279 return (owner_data->LockThisFrame ==
false);
12285 if (owner_data->OwnerCurr != owner_id)
12287 if (owner_data->LockThisFrame)
12289 if (owner_data->OwnerCurr != ImGuiKeyOwner_NoOwner)
12301void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
12304 IM_ASSERT(IsNamedKeyOrMod(key) &&
12305 (owner_id != ImGuiKeyOwner_Any ||
12306 (flags & (ImGuiInputFlags_LockThisFrame |
12307 ImGuiInputFlags_LockUntilRelease))));
12309 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetKeyOwner) == 0);
12313 owner_data->OwnerCurr = owner_data->OwnerNext = owner_id;
12318 owner_data->LockUntilRelease = (flags & ImGuiInputFlags_LockUntilRelease) != 0;
12319 owner_data->LockThisFrame = (flags & ImGuiInputFlags_LockThisFrame) != 0 || (owner_data->LockUntilRelease);
12323void ImGui::SetKeyOwnersForKeyChord(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
12325 if (key_chord & ImGuiMod_Ctrl)
12327 SetKeyOwner(ImGuiMod_Ctrl, owner_id, flags);
12329 if (key_chord & ImGuiMod_Shift)
12331 SetKeyOwner(ImGuiMod_Shift, owner_id, flags);
12333 if (key_chord & ImGuiMod_Alt)
12335 SetKeyOwner(ImGuiMod_Alt, owner_id, flags);
12337 if (key_chord & ImGuiMod_Super)
12339 SetKeyOwner(ImGuiMod_Super, owner_id, flags);
12341 if (key_chord & ~ImGuiMod_Mask_)
12343 SetKeyOwner((ImGuiKey)(key_chord & ~ImGuiMod_Mask_), owner_id, flags);
12354void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
12357 ImGuiID
id = g.LastItemData.ID;
12358 if (
id == 0 || (g.HoveredId !=
id && g.ActiveId !=
id))
12360 if ((flags & ImGuiInputFlags_CondMask_) == 0)
12361 flags |= ImGuiInputFlags_CondDefault_;
12362 if ((g.HoveredId ==
id && (flags & ImGuiInputFlags_CondHovered)) ||
12363 (g.ActiveId ==
id && (flags & ImGuiInputFlags_CondActive)))
12365 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetItemKeyOwner) ==
12367 SetKeyOwner(key,
id, flags & ~ImGuiInputFlags_CondMask_);
12371void ImGui::SetItemKeyOwner(ImGuiKey key)
12373 SetItemKeyOwner(key, ImGuiInputFlags_None);
12377bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord)
12379 return IsKeyChordPressed(key_chord, ImGuiInputFlags_None, ImGuiKeyOwner_Any);
12383bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)
12386 key_chord = FixupKeyChord(key_chord);
12387 ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
12388 if (g.IO.KeyMods != mods)
12392 ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
12393 if (key == ImGuiKey_None)
12394 key = ConvertSingleModFlagToKey(mods);
12395 if (!
IsKeyPressed(key, (flags & ImGuiInputFlags_RepeatMask_), owner_id))
12400void ImGui::SetNextItemShortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags)
12403 g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasShortcut;
12404 g.NextItemData.Shortcut = key_chord;
12405 g.NextItemData.ShortcutFlags = flags;
12409void ImGui::ItemHandleShortcut(ImGuiID
id)
12412 ImGuiInputFlags flags = g.NextItemData.ShortcutFlags;
12413 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetNextItemShortcut) ==
12416 if (g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled)
12418 if (flags & ImGuiInputFlags_Tooltip)
12420 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasShortcut;
12421 g.LastItemData.Shortcut = g.NextItemData.Shortcut;
12423 if (!Shortcut(g.NextItemData.Shortcut, flags & ImGuiInputFlags_SupportedByShortcut,
id) || g.NavActivateId != 0)
12427 g.NavActivateId = id;
12428 g.NavActivateFlags = ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_FromShortcut;
12430 g.NavActivateDownId = g.NavActivatePressedId = id;
12431 NavHighlightActivated(
id);
12434bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags)
12436 return Shortcut(key_chord, flags, ImGuiKeyOwner_Any);
12439bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)
12447 if ((flags & ImGuiInputFlags_RouteTypeMask_) == 0)
12448 flags |= ImGuiInputFlags_RouteFocused;
12452 if (owner_id == ImGuiKeyOwner_Any || owner_id == ImGuiKeyOwner_NoOwner)
12453 owner_id = GetRoutingIdFromOwnerId(owner_id);
12455 if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
12459 if (!SetShortcutRouting(key_chord, flags, owner_id))
12464 if ((flags & ImGuiInputFlags_Repeat) != 0 && (flags & ImGuiInputFlags_RepeatUntilMask_) == 0)
12465 flags |= ImGuiInputFlags_RepeatUntilKeyModsChange;
12467 if (!IsKeyChordPressed(key_chord, flags, owner_id))
12471 SetKeyOwnersForKeyChord(key_chord & ImGuiMod_Mask_, owner_id);
12473 IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0);
12500bool ImGui::DebugCheckVersionAndDataLayout(
const char *version,
size_t sz_io,
size_t sz_style,
size_t sz_vec2,
12501 size_t sz_vec4,
size_t sz_vert,
size_t sz_idx)
12503 bool error =
false;
12504 if (strcmp(version, IMGUI_VERSION) != 0)
12507 IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 &&
"Mismatched version string!");
12509 if (sz_io !=
sizeof(
ImGuiIO))
12512 IM_ASSERT(sz_io ==
sizeof(
ImGuiIO) &&
"Mismatched struct layout!");
12517 IM_ASSERT(sz_style ==
sizeof(
ImGuiStyle) &&
"Mismatched struct layout!");
12519 if (sz_vec2 !=
sizeof(
ImVec2))
12522 IM_ASSERT(sz_vec2 ==
sizeof(
ImVec2) &&
"Mismatched struct layout!");
12524 if (sz_vec4 !=
sizeof(
ImVec4))
12527 IM_ASSERT(sz_vec4 ==
sizeof(
ImVec4) &&
"Mismatched struct layout!");
12532 IM_ASSERT(sz_vert ==
sizeof(
ImDrawVert) &&
"Mismatched struct layout!");
12534 if (sz_idx !=
sizeof(ImDrawIdx))
12537 IM_ASSERT(sz_idx ==
sizeof(ImDrawIdx) &&
"Mismatched struct layout!");
12558void ImGui::ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
12562 IM_ASSERT(window->DC.IsSetPos);
12563 window->DC.IsSetPos =
false;
12564#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
12565 if (window->DC.CursorPos.x <= window->DC.CursorMaxPos.x && window->DC.CursorPos.y <= window->DC.CursorMaxPos.y)
12567 if (window->SkipItems)
12569 IM_ASSERT(0 &&
"Code uses SetCursorPos()/SetCursorScreenPos() to extend window/parent boundaries. Please submit an "
12570 "item e.g. Dummy() to validate extent.");
12572 window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
12576static void ImGui::ErrorCheckNewFrameSanityChecks()
12594#ifdef __EMSCRIPTEN__
12595 if (g.IO.DeltaTime <= 0.0f && g.FrameCount > 0)
12596 g.IO.DeltaTime = 0.00001f;
12602 IM_ASSERT(g.Initialized);
12603 IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) &&
"Need a positive DeltaTime!");
12604 IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) &&
12605 "Forgot to call Render() or EndFrame() at the end of the previous frame?");
12606 IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f &&
"Invalid DisplaySize value!");
12607 IM_ASSERT(g.IO.Fonts->IsBuilt() &&
12608 "Font Atlas not built! Make sure you called ImGui_ImplXXXX_NewFrame() function for renderer backend, "
12609 "which should call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()");
12610 IM_ASSERT(g.Style.CurveTessellationTol > 0.0f &&
"Invalid style setting!");
12611 IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f &&
"Invalid style setting!");
12612 IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f &&
12613 "Invalid style setting!");
12614 IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f &&
"Invalid style setting!");
12615 IM_ASSERT(g.Style.WindowBorderHoverPadding > 0.0f &&
12616 "Invalid style setting!");
12617 IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left ||
12618 g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
12619 IM_ASSERT(g.Style.ColorButtonPosition == ImGuiDir_Left || g.Style.ColorButtonPosition == ImGuiDir_Right);
12622 if (g.IO.ConfigErrorRecovery)
12623 IM_ASSERT(g.IO.ConfigErrorRecoveryEnableAssert || g.IO.ConfigErrorRecoveryEnableDebugLog ||
12624 g.IO.ConfigErrorRecoveryEnableTooltip || g.ErrorCallback != NULL);
12626#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
12628 if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)
12630 g.IO.ConfigNavMoveSetMousePos =
true;
12631 g.IO.ConfigFlags &= ~ImGuiConfigFlags_NavEnableSetMousePos;
12633 if (g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)
12635 g.IO.ConfigNavCaptureKeyboard =
false;
12636 g.IO.ConfigFlags &= ~ImGuiConfigFlags_NavNoCaptureKeyboard;
12640 if (g.IO.GetClipboardTextFn != NULL &&
12641 (g.PlatformIO.Platform_GetClipboardTextFn == NULL ||
12642 g.PlatformIO.Platform_GetClipboardTextFn == Platform_GetClipboardTextFn_DefaultImpl))
12643 g.PlatformIO.Platform_GetClipboardTextFn = [](
ImGuiContext *ctx) {
12644 return ctx->IO.GetClipboardTextFn(ctx->IO.ClipboardUserData);
12646 if (g.IO.SetClipboardTextFn != NULL &&
12647 (g.PlatformIO.Platform_SetClipboardTextFn == NULL ||
12648 g.PlatformIO.Platform_SetClipboardTextFn == Platform_SetClipboardTextFn_DefaultImpl))
12649 g.PlatformIO.Platform_SetClipboardTextFn = [](
ImGuiContext *ctx,
const char *text) {
12650 return ctx->IO.SetClipboardTextFn(ctx->IO.ClipboardUserData, text);
12656 if (g.FrameCount == 1 && (g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable) &&
12657 (g.ConfigFlagsLastFrame & ImGuiConfigFlags_DockingEnable) == 0)
12658 IM_ASSERT(0 &&
"Please set DockingEnable before the first call to NewFrame()! Otherwise you will lose your "
12660 if (g.FrameCount == 1 && (g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) &&
12661 (g.ConfigFlagsLastFrame & ImGuiConfigFlags_ViewportsEnable) == 0)
12662 IM_ASSERT(0 &&
"Please set ViewportsEnable before the first call to NewFrame()! Otherwise you will lose your "
12666 if (g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
12668 if ((g.IO.BackendFlags & ImGuiBackendFlags_PlatformHasViewports) &&
12669 (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasViewports))
12671 IM_ASSERT((g.FrameCount == 0 || g.FrameCount == g.FrameCountPlatformEnded) &&
12672 "Forgot to call UpdatePlatformWindows() in main loop after EndFrame()? Check examples/ "
12673 "applications for reference.");
12674 IM_ASSERT(g.PlatformIO.Platform_CreateWindow != NULL &&
"Platform init didn't install handlers?");
12675 IM_ASSERT(g.PlatformIO.Platform_DestroyWindow != NULL &&
"Platform init didn't install handlers?");
12676 IM_ASSERT(g.PlatformIO.Platform_GetWindowPos != NULL &&
"Platform init didn't install handlers?");
12677 IM_ASSERT(g.PlatformIO.Platform_SetWindowPos != NULL &&
"Platform init didn't install handlers?");
12678 IM_ASSERT(g.PlatformIO.Platform_GetWindowSize != NULL &&
"Platform init didn't install handlers?");
12679 IM_ASSERT(g.PlatformIO.Platform_SetWindowSize != NULL &&
"Platform init didn't install handlers?");
12680 IM_ASSERT(g.PlatformIO.Monitors.Size > 0 &&
"Platform init didn't setup Monitors list?");
12681 IM_ASSERT((g.Viewports[0]->PlatformUserData != NULL || g.Viewports[0]->PlatformHandle != NULL) &&
12682 "Platform init didn't setup main viewport.");
12683 if (g.IO.ConfigDockingTransparentPayload && (g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
12684 IM_ASSERT(g.PlatformIO.Platform_SetWindowAlpha != NULL &&
12685 "Platform_SetWindowAlpha handler is required to use io.ConfigDockingTransparent!");
12690 g.IO.ConfigFlags &= ~ImGuiConfigFlags_ViewportsEnable;
12697 IM_ASSERT(mon.MainSize.x > 0.0f && mon.MainSize.y > 0.0f &&
"Monitor main bounds not setup properly.");
12698 IM_ASSERT(
ImRect(mon.MainPos, mon.MainPos + mon.MainSize)
12699 .Contains(
ImRect(mon.WorkPos, mon.WorkPos + mon.WorkSize)) &&
12700 "Monitor work bounds not setup properly. If you don't have work area information, just copy "
12701 "MainPos/MainSize into them.");
12702 IM_ASSERT(mon.DpiScale > 0.0f && mon.DpiScale < 99.0f &&
12703 "Monitor DpiScale is invalid.");
12708static void ImGui::ErrorCheckEndFrameSanityChecks()
12717 const ImGuiKeyChord key_mods = GetMergedModsFromKeys();
12719 IM_UNUSED(key_mods);
12720 IM_ASSERT((key_mods == 0 || g.IO.KeyMods == key_mods) &&
12721 "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
12722 IM_UNUSED(key_mods);
12724 IM_ASSERT(g.CurrentWindowStack.Size == 1);
12725 IM_ASSERT(g.CurrentWindowStack[0].Window->IsFallbackWindow);
12732 state_out->SizeOfWindowStack = (short)g.CurrentWindowStack.Size;
12733 state_out->SizeOfIDStack = (short)g.CurrentWindow->IDStack.Size;
12734 state_out->SizeOfTreeStack =
12735 (short)g.CurrentWindow->DC.TreeDepth;
12736 state_out->SizeOfColorStack = (short)g.ColorStack.Size;
12737 state_out->SizeOfStyleVarStack = (short)g.StyleVarStack.Size;
12738 state_out->SizeOfFontStack = (short)g.FontStack.Size;
12739 state_out->SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size;
12740 state_out->SizeOfGroupStack = (short)g.GroupStack.Size;
12741 state_out->SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size;
12742 state_out->SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size;
12743 state_out->SizeOfDisabledStack = (short)g.DisabledStackSize;
12753 while (g.CurrentWindowStack.Size > state_in->SizeOfWindowStack)
12761 if (window->Flags & ImGuiWindowFlags_ChildWindow)
12763 if (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow)
12765 IM_ASSERT_USER_ERROR(0,
"Missing EndTable()");
12770 IM_ASSERT_USER_ERROR(0,
"Missing EndChild()");
12776 IM_ASSERT_USER_ERROR(0,
"Missing End()");
12780 if (g.CurrentWindowStack.Size == state_in->SizeOfWindowStack)
12781 ErrorRecoveryTryToRecoverWindowState(state_in);
12791 while (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow)
12793 IM_ASSERT_USER_ERROR(0,
"Missing EndTable()");
12800 while (g.CurrentTabBar != NULL && g.CurrentTabBar->Window == window)
12802 IM_ASSERT_USER_ERROR(0,
"Missing EndTabBar()");
12805 while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window)
12807 IM_ASSERT_USER_ERROR(0,
"Missing EndMultiSelect()");
12810 if (window->DC.MenuBarAppending)
12812 IM_ASSERT_USER_ERROR(0,
"Missing EndMenuBar()");
12815 while (window->DC.TreeDepth > state_in->SizeOfTreeStack)
12817 IM_ASSERT_USER_ERROR(0,
"Missing TreePop()");
12820 while (g.GroupStack.Size > state_in->SizeOfGroupStack)
12822 IM_ASSERT_USER_ERROR(0,
"Missing EndGroup()");
12825 IM_ASSERT(g.GroupStack.Size == state_in->SizeOfGroupStack);
12826 while (window->IDStack.Size > state_in->SizeOfIDStack)
12828 IM_ASSERT_USER_ERROR(0,
"Missing PopID()");
12831 while (g.DisabledStackSize > state_in->SizeOfDisabledStack)
12833 IM_ASSERT_USER_ERROR(0,
"Missing EndDisabled()");
12834 if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
12838 EndDisabledOverrideReenable();
12839 g.CurrentWindowStack.back().DisabledOverrideReenable =
false;
12842 IM_ASSERT(g.DisabledStackSize == state_in->SizeOfDisabledStack);
12843 while (g.ColorStack.Size > state_in->SizeOfColorStack)
12845 IM_ASSERT_USER_ERROR(0,
"Missing PopStyleColor()");
12848 while (g.ItemFlagsStack.Size > state_in->SizeOfItemFlagsStack)
12850 IM_ASSERT_USER_ERROR(0,
"Missing PopItemFlag()");
12853 while (g.StyleVarStack.Size > state_in->SizeOfStyleVarStack)
12855 IM_ASSERT_USER_ERROR(0,
"Missing PopStyleVar()");
12858 while (g.FontStack.Size > state_in->SizeOfFontStack)
12860 IM_ASSERT_USER_ERROR(0,
"Missing PopFont()");
12863 while (g.FocusScopeStack.Size > state_in->SizeOfFocusScopeStack)
12865 IM_ASSERT_USER_ERROR(0,
"Missing PopFocusScope()");
12871bool ImGui::ErrorLog(
const char *msg)
12876#ifndef IMGUI_DISABLE_DEBUG_TOOLS
12879 if (g.IO.ConfigErrorRecoveryEnableDebugLog)
12882 IMGUI_DEBUG_LOG_ERROR(
"[imgui-error] (current settings: Assert=%d, Log=%d, Tooltip=%d)\n",
12883 g.IO.ConfigErrorRecoveryEnableAssert, g.IO.ConfigErrorRecoveryEnableDebugLog,
12884 g.IO.ConfigErrorRecoveryEnableTooltip);
12885 IMGUI_DEBUG_LOG_ERROR(
"[imgui-error] In window '%s': %s\n", window ? window->Name :
"NULL", msg);
12887 g.ErrorFirst =
false;
12890 if (g.IO.ConfigErrorRecoveryEnableTooltip)
12892 if (g.WithinFrameScope && BeginErrorTooltip())
12894 if (g.ErrorCountCurrentFrame < 20)
12896 Text(
"In window '%s': %s", window ? window->Name :
"NULL", msg);
12897 if (window && (!window->IsFallbackWindow || window->WasActive))
12898 GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size,
12899 IM_COL32(255, 0, 0, 255));
12901 if (g.ErrorCountCurrentFrame == 20)
12902 Text(
"(and more errors)");
12906 g.ErrorCountCurrentFrame++;
12911 if (g.ErrorCallback != NULL)
12912 g.ErrorCallback(&g, g.ErrorCallbackUserData, msg);
12915 return g.IO.ConfigErrorRecoveryEnableAssert;
12918void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
12920#ifndef IMGUI_DISABLE_DEBUG_TOOLS
12922 if (g.DebugDrawIdConflicts != 0 && g.IO.KeyCtrl ==
false)
12923 g.DebugDrawIdConflictsCount = g.HoveredIdPreviousFrameItemCount;
12924 if (g.DebugDrawIdConflicts != 0 && g.DebugItemPickerActive ==
false && BeginErrorTooltip())
12926 Text(
"Programmer error: %d visible items with conflicting ID!", g.DebugDrawIdConflictsCount);
12927 BulletText(
"Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
12928 BulletText(
"Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
12931 BulletText(
"Set io.ConfigDebugHighlightIdConflicts=false to disable this warning in non-programmers builds.");
12933 if (g.IO.ConfigDebugHighlightIdConflictsShowItemPicker)
12935 Text(
"(Hold CTRL to: use ");
12936 SameLine(0.0f, 0.0f);
12937 if (SmallButton(
"Item Picker"))
12938 DebugStartItemPicker();
12939 SameLine(0.0f, 0.0f);
12940 Text(
" to break in item call-stack, or ");
12944 Text(
"(Hold CTRL to ");
12946 SameLine(0.0f, 0.0f);
12947 if (SmallButton(
"Open FAQ->About ID Stack System") && g.PlatformIO.Platform_OpenInShellFn != NULL)
12948 g.PlatformIO.Platform_OpenInShellFn(&g,
12949 "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
12950 SameLine(0.0f, 0.0f);
12955 if (g.ErrorCountCurrentFrame > 0 && BeginErrorTooltip())
12958 Text(
"(Hold CTRL to:");
12960 if (SmallButton(
"Enable Asserts"))
12961 g.IO.ConfigErrorRecoveryEnableAssert =
true;
12973bool ImGui::BeginErrorTooltip()
12976 ImGuiWindow *window = FindWindowByName(
"##Tooltip_Error");
12977 const bool use_locked_pos = (g.IO.KeyCtrl && window && window->WasActive);
12978 PushStyleColor(ImGuiCol_PopupBg, ImLerp(g.Style.Colors[ImGuiCol_PopupBg],
ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.15f));
12979 if (use_locked_pos)
12980 SetNextWindowPos(g.ErrorTooltipLockedPos);
12982 Begin(
"##Tooltip_Error", NULL,
12983 ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
12984 ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize);
12986 if (is_visible && g.CurrentWindow->BeginCount == 1)
12988 SeparatorText(
"MESSAGE FROM DEAR IMGUI");
12989 BringWindowToDisplayFront(g.CurrentWindow);
12990 BringWindowToFocusFront(g.CurrentWindow);
12991 g.ErrorTooltipLockedPos = GetWindowPos();
12993 else if (!is_visible)
13000void ImGui::EndErrorTooltip()
13014void ImGui::KeepAliveID(ImGuiID
id)
13017 if (g.ActiveId ==
id)
13018 g.ActiveIdIsAlive = id;
13019 if (g.DeactivatedItemData.ID ==
id)
13020 g.DeactivatedItemData.IsAlive =
true;
13027IM_MSVC_RUNTIME_CHECKS_OFF
13028bool ImGui::ItemAdd(
const ImRect &bb, ImGuiID
id,
const ImRect *nav_bb_arg, ImGuiItemFlags extra_flags)
13035 g.LastItemData.ID = id;
13036 g.LastItemData.Rect = bb;
13037 g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb;
13038 g.LastItemData.ItemFlags = g.CurrentItemFlags | g.NextItemData.ItemFlags | extra_flags;
13039 g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None;
13059 if (!(g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav))
13063 window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent);
13064 if (g.NavId ==
id || g.NavAnyRequest)
13065 if (g.NavWindow->RootWindowForNav == window->RootWindowForNav)
13066 if (window == g.NavWindow ||
13067 ((window->ChildFlags | g.NavWindow->ChildFlags) & ImGuiChildFlags_NavFlattened))
13071 if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasShortcut)
13072 ItemHandleShortcut(
id);
13076 g.NextItemData.HasFlags = ImGuiNextItemDataFlags_None;
13077 g.NextItemData.ItemFlags = ImGuiItemFlags_None;
13079#ifdef IMGUI_ENABLE_TEST_ENGINE
13081 IMGUI_TEST_ENGINE_ITEM_ADD(
id, g.LastItemData.NavRect, &g.LastItemData);
13088 const bool is_rect_visible = bb.Overlaps(window->ClipRect);
13089 if (!is_rect_visible)
13090 if (
id == 0 || (
id != g.ActiveId &&
id != g.ActiveIdPreviousFrame &&
id != g.NavId &&
id != g.NavActivateId))
13091 if (!g.ItemUnclipByLog)
13095#ifndef IMGUI_DISABLE_DEBUG_TOOLS
13098 if (
id == g.DebugLocateId)
13099 DebugLocateItemResolveWithLastItem();
13104 IM_ASSERT(
id != window->ID &&
"Cannot have an empty ID at the root of a window. If you need an empty label, "
13105 "use ## and read the FAQ about how the ID Stack works!");
13113 if (
id != 0 && g.DeactivatedItemData.ID ==
id)
13114 g.DeactivatedItemData.ElapseFrame = g.FrameCount;
13118 if (is_rect_visible)
13119 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible;
13120 if (IsMouseHoveringRect(bb.Min, bb.Max))
13121 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
13124IM_MSVC_RUNTIME_CHECKS_RESTORE
13159IM_MSVC_RUNTIME_CHECKS_OFF
13160void ImGui::ItemSize(
const ImVec2 &size,
float text_baseline_y)
13164 if (window->SkipItems)
13171 const float offset_to_match_baseline_y =
13172 (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f;
13174 const float line_y1 = window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y;
13175 const float line_height = ImMax(window->DC.CurrLineSize.y, window->DC.CursorPos.y - line_y1 +
13176 size.y + offset_to_match_baseline_y);
13181 window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x;
13182 window->DC.CursorPosPrevLine.y = line_y1;
13183 window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
13184 window->DC.CursorPos.y = IM_TRUNC(line_y1 + line_height + g.Style.ItemSpacing.y);
13185 window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
13186 window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y);
13189 window->DC.PrevLineSize.y = line_height;
13190 window->DC.CurrLineSize.y = 0.0f;
13191 window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y);
13192 window->DC.CurrLineTextBaseOffset = 0.0f;
13193 window->DC.IsSameLine = window->DC.IsSetPos =
false;
13196 if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
13199IM_MSVC_RUNTIME_CHECKS_RESTORE
13206void ImGui::SameLine(
float offset_from_start_x,
float spacing_w)
13210 if (window->SkipItems)
13213 if (offset_from_start_x != 0.0f)
13215 if (spacing_w < 0.0f)
13217 window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing_w +
13218 window->DC.GroupOffset.x + window->DC.ColumnsOffset.x;
13219 window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
13223 if (spacing_w < 0.0f)
13224 spacing_w = g.Style.ItemSpacing.x;
13225 window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
13226 window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
13228 window->DC.CurrLineSize = window->DC.PrevLineSize;
13229 window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
13230 window->DC.IsSameLine =
true;
13233ImVec2 ImGui::GetCursorScreenPos()
13236 return window->DC.CursorPos;
13239void ImGui::SetCursorScreenPos(
const ImVec2 &pos)
13242 window->DC.CursorPos = pos;
13244 window->DC.IsSetPos =
true;
13250ImVec2 ImGui::GetCursorPos()
13253 return window->DC.CursorPos - window->Pos + window->Scroll;
13256float ImGui::GetCursorPosX()
13259 return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x;
13262float ImGui::GetCursorPosY()
13265 return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y;
13268void ImGui::SetCursorPos(
const ImVec2 &local_pos)
13271 window->DC.CursorPos = window->Pos - window->Scroll + local_pos;
13273 window->DC.IsSetPos =
true;
13276void ImGui::SetCursorPosX(
float x)
13279 window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;
13281 window->DC.IsSetPos =
true;
13284void ImGui::SetCursorPosY(
float y)
13287 window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;
13289 window->DC.IsSetPos =
true;
13292ImVec2 ImGui::GetCursorStartPos()
13295 return window->DC.CursorStartPos - window->Pos;
13298void ImGui::Indent(
float indent_w)
13302 window->DC.Indent.x += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
13303 window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
13306void ImGui::Unindent(
float indent_w)
13310 window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
13311 window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
13315void ImGui::SetNextItemWidth(
float item_width)
13318 g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasWidth;
13319 g.NextItemData.Width = item_width;
13323void ImGui::PushItemWidth(
float item_width)
13327 window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
13328 window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
13329 g.NextItemData.HasFlags &= ~ImGuiNextItemDataFlags_HasWidth;
13332void ImGui::PushMultiItemsWidths(
int components,
float w_full)
13336 IM_ASSERT(components > 0);
13338 window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
13339 float w_items = w_full - style.ItemInnerSpacing.x * (components - 1);
13340 float prev_split = w_items;
13341 for (
int i = components - 1; i > 0; i--)
13343 float next_split = IM_TRUNC(w_items * i / components);
13344 window->DC.ItemWidthStack.push_back(ImMax(prev_split - next_split, 1.0f));
13345 prev_split = next_split;
13347 window->DC.ItemWidth = ImMax(prev_split, 1.0f);
13348 g.NextItemData.HasFlags &= ~ImGuiNextItemDataFlags_HasWidth;
13351void ImGui::PopItemWidth()
13355 if (window->DC.ItemWidthStack.Size <= 0)
13357 IM_ASSERT_USER_ERROR(0,
"Calling PopItemWidth() too many times!");
13360 window->DC.ItemWidth = window->DC.ItemWidthStack.back();
13361 window->DC.ItemWidthStack.pop_back();
13366float ImGui::CalcItemWidth()
13371 if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasWidth)
13372 w = g.NextItemData.Width;
13374 w = window->DC.ItemWidth;
13377 float region_avail_x = GetContentRegionAvail().x;
13378 w = ImMax(1.0f, region_avail_x + w);
13388ImVec2 ImGui::CalcItemSize(
ImVec2 size,
float default_w,
float default_h)
13391 if (size.x < 0.0f || size.y < 0.0f)
13392 avail = GetContentRegionAvail();
13394 if (size.x == 0.0f)
13395 size.x = default_w;
13396 else if (size.x < 0.0f)
13397 size.x = ImMax(4.0f, avail.x + size.x);
13399 if (size.y == 0.0f)
13400 size.y = default_h;
13401 else if (size.y < 0.0f)
13402 size.y = ImMax(4.0f, avail.y + size.y);
13407float ImGui::GetTextLineHeight()
13413float ImGui::GetTextLineHeightWithSpacing()
13416 return g.FontSize + g.Style.ItemSpacing.y;
13419float ImGui::GetFrameHeight()
13422 return g.FontSize + g.Style.FramePadding.y * 2.0f;
13425float ImGui::GetFrameHeightWithSpacing()
13428 return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y;
13431ImVec2 ImGui::GetContentRegionAvail()
13435 ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max;
13436 return mx - window->DC.CursorPos;
13439#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
13443ImVec2 ImGui::GetContentRegionMax()
13445 return GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos();
13448ImVec2 ImGui::GetWindowContentRegionMin()
13451 return window->ContentRegionRect.Min - window->Pos;
13454ImVec2 ImGui::GetWindowContentRegionMax()
13457 return window->ContentRegionRect.Max - window->Pos;
13465void ImGui::BeginGroup()
13470 g.GroupStack.resize(g.GroupStack.Size + 1);
13472 group_data.WindowID = window->ID;
13473 group_data.BackupCursorPos = window->DC.CursorPos;
13474 group_data.BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
13475 group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
13476 group_data.BackupIndent = window->DC.Indent;
13477 group_data.BackupGroupOffset = window->DC.GroupOffset;
13478 group_data.BackupCurrLineSize = window->DC.CurrLineSize;
13479 group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
13480 group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
13481 group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
13482 group_data.BackupIsSameLine = window->DC.IsSameLine;
13483 group_data.BackupDeactivatedIdIsAlive = g.DeactivatedItemData.IsAlive;
13484 group_data.EmitItem =
true;
13486 window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
13487 window->DC.Indent = window->DC.GroupOffset;
13488 window->DC.CursorMaxPos = window->DC.CursorPos;
13489 window->DC.CurrLineSize =
ImVec2(0.0f, 0.0f);
13491 g.LogLinePosY = -FLT_MAX;
13494void ImGui::EndGroup()
13498 IM_ASSERT(g.GroupStack.Size > 0);
13501 IM_ASSERT(group_data.WindowID == window->ID);
13503 if (window->DC.IsSetPos)
13504 ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
13507 ImRect group_bb(group_data.BackupCursorPos,
13508 ImMax(ImMax(window->DC.CursorMaxPos, g.LastItemData.Rect.Max), group_data.BackupCursorPos));
13509 window->DC.CursorPos = group_data.BackupCursorPos;
13510 window->DC.CursorPosPrevLine = group_data.BackupCursorPosPrevLine;
13511 window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, group_bb.Max);
13512 window->DC.Indent = group_data.BackupIndent;
13513 window->DC.GroupOffset = group_data.BackupGroupOffset;
13514 window->DC.CurrLineSize = group_data.BackupCurrLineSize;
13515 window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
13516 window->DC.IsSameLine = group_data.BackupIsSameLine;
13518 g.LogLinePosY = -FLT_MAX;
13520 if (!group_data.EmitItem)
13522 g.GroupStack.pop_back();
13526 window->DC.CurrLineTextBaseOffset =
13527 ImMax(window->DC.PrevLineTextBaseOffset,
13528 group_data.BackupCurrLineTextBaseOffset);
13530 ItemSize(group_bb.GetSize());
13531 ItemAdd(group_bb, 0, NULL, ImGuiItemFlags_NoTabStop);
13539 const bool group_contains_curr_active_id =
13540 (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId;
13541 const bool group_contains_deactivated_id =
13542 (group_data.BackupDeactivatedIdIsAlive ==
false) && (g.DeactivatedItemData.IsAlive ==
true);
13543 if (group_contains_curr_active_id)
13544 g.LastItemData.ID = g.ActiveId;
13545 else if (group_contains_deactivated_id)
13546 g.LastItemData.ID = g.DeactivatedItemData.ID;
13547 g.LastItemData.Rect = group_bb;
13550 const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive ==
false) && g.HoveredId != 0;
13551 if (group_contains_curr_hovered_id)
13552 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
13555 if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)
13556 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
13559 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
13560 if (group_contains_deactivated_id)
13561 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated;
13563 g.GroupStack.pop_back();
13564 if (g.DebugShowGroupRects)
13565 window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255, 0, 255, 255));
13577static float CalcScrollEdgeSnap(
float target,
float snap_min,
float snap_max,
float snap_threshold,
float center_ratio)
13579 if (target <= snap_min + snap_threshold)
13580 return ImLerp(snap_min, target, center_ratio);
13581 if (target >= snap_max - snap_threshold)
13582 return ImLerp(target, snap_max, center_ratio);
13588 ImVec2 scroll = window->Scroll;
13589 ImVec2 decoration_size(window->DecoOuterSizeX1 + window->DecoInnerSizeX1 + window->DecoOuterSizeX2,
13590 window->DecoOuterSizeY1 + window->DecoInnerSizeY1 + window->DecoOuterSizeY2);
13591 for (
int axis = 0; axis < 2; axis++)
13593 if (window->ScrollTarget[axis] < FLT_MAX)
13595 float center_ratio = window->ScrollTargetCenterRatio[axis];
13596 float scroll_target = window->ScrollTarget[axis];
13597 if (window->ScrollTargetEdgeSnapDist[axis] > 0.0f)
13599 float snap_min = 0.0f;
13600 float snap_max = window->ScrollMax[axis] + window->SizeFull[axis] - decoration_size[axis];
13601 scroll_target = CalcScrollEdgeSnap(scroll_target, snap_min, snap_max,
13602 window->ScrollTargetEdgeSnapDist[axis], center_ratio);
13604 scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]);
13606 scroll[axis] = IM_ROUND(ImMax(scroll[axis], 0.0f));
13607 if (!window->Collapsed && !window->SkipItems)
13608 scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]);
13613void ImGui::ScrollToItem(ImGuiScrollFlags flags)
13617 ScrollToRectEx(window, g.LastItemData.NavRect, flags);
13620void ImGui::ScrollToRect(
ImGuiWindow *window,
const ImRect &item_rect, ImGuiScrollFlags flags)
13622 ScrollToRectEx(window, item_rect, flags);
13629 ImRect scroll_rect(window->InnerRect.Min -
ImVec2(1, 1), window->InnerRect.Max +
ImVec2(1, 1));
13630 scroll_rect.Min.x = ImMin(scroll_rect.Min.x + window->DecoInnerSizeX1, scroll_rect.Max.x);
13631 scroll_rect.Min.y = ImMin(scroll_rect.Min.y + window->DecoInnerSizeY1, scroll_rect.Max.y);
13636 IM_ASSERT((flags & ImGuiScrollFlags_MaskX_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskX_));
13637 IM_ASSERT((flags & ImGuiScrollFlags_MaskY_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskY_));
13640 ImGuiScrollFlags in_flags = flags;
13641 if ((flags & ImGuiScrollFlags_MaskX_) == 0 && window->ScrollbarX)
13642 flags |= ImGuiScrollFlags_KeepVisibleEdgeX;
13643 if ((flags & ImGuiScrollFlags_MaskY_) == 0)
13644 flags |= window->Appearing ? ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeY;
13646 const bool fully_visible_x = item_rect.Min.x >= scroll_rect.Min.x && item_rect.Max.x <= scroll_rect.Max.x;
13647 const bool fully_visible_y = item_rect.Min.y >= scroll_rect.Min.y && item_rect.Max.y <= scroll_rect.Max.y;
13648 const bool can_be_fully_visible_x =
13649 (item_rect.GetWidth() + g.Style.ItemSpacing.x * 2.0f) <= scroll_rect.GetWidth() ||
13650 (window->AutoFitFramesX > 0) || (window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0;
13651 const bool can_be_fully_visible_y =
13652 (item_rect.GetHeight() + g.Style.ItemSpacing.y * 2.0f) <= scroll_rect.GetHeight() ||
13653 (window->AutoFitFramesY > 0) || (window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0;
13655 if ((flags & ImGuiScrollFlags_KeepVisibleEdgeX) && !fully_visible_x)
13657 if (item_rect.Min.x < scroll_rect.Min.x || !can_be_fully_visible_x)
13658 SetScrollFromPosX(window, item_rect.Min.x - g.Style.ItemSpacing.x - window->Pos.x, 0.0f);
13659 else if (item_rect.Max.x >= scroll_rect.Max.x)
13660 SetScrollFromPosX(window, item_rect.Max.x + g.Style.ItemSpacing.x - window->Pos.x, 1.0f);
13662 else if (((flags & ImGuiScrollFlags_KeepVisibleCenterX) && !fully_visible_x) ||
13663 (flags & ImGuiScrollFlags_AlwaysCenterX))
13665 if (can_be_fully_visible_x)
13666 SetScrollFromPosX(window, ImTrunc((item_rect.Min.x + item_rect.Max.x) * 0.5f) - window->Pos.x, 0.5f);
13668 SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x, 0.0f);
13671 if ((flags & ImGuiScrollFlags_KeepVisibleEdgeY) && !fully_visible_y)
13673 if (item_rect.Min.y < scroll_rect.Min.y || !can_be_fully_visible_y)
13674 SetScrollFromPosY(window, item_rect.Min.y - g.Style.ItemSpacing.y - window->Pos.y, 0.0f);
13675 else if (item_rect.Max.y >= scroll_rect.Max.y)
13676 SetScrollFromPosY(window, item_rect.Max.y + g.Style.ItemSpacing.y - window->Pos.y, 1.0f);
13678 else if (((flags & ImGuiScrollFlags_KeepVisibleCenterY) && !fully_visible_y) ||
13679 (flags & ImGuiScrollFlags_AlwaysCenterY))
13681 if (can_be_fully_visible_y)
13682 SetScrollFromPosY(window, ImTrunc((item_rect.Min.y + item_rect.Max.y) * 0.5f) - window->Pos.y, 0.5f);
13684 SetScrollFromPosY(window, item_rect.Min.y - window->Pos.y, 0.0f);
13687 ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
13688 ImVec2 delta_scroll = next_scroll - window->Scroll;
13691 if (!(flags & ImGuiScrollFlags_NoScrollParent) && (window->Flags & ImGuiWindowFlags_ChildWindow))
13694 if ((in_flags & (ImGuiScrollFlags_AlwaysCenterX | ImGuiScrollFlags_KeepVisibleCenterX)) != 0)
13695 in_flags = (in_flags & ~ImGuiScrollFlags_MaskX_) | ImGuiScrollFlags_KeepVisibleEdgeX;
13696 if ((in_flags & (ImGuiScrollFlags_AlwaysCenterY | ImGuiScrollFlags_KeepVisibleCenterY)) != 0)
13697 in_flags = (in_flags & ~ImGuiScrollFlags_MaskY_) | ImGuiScrollFlags_KeepVisibleEdgeY;
13698 delta_scroll += ScrollToRectEx(window->ParentWindow,
13699 ImRect(item_rect.Min - delta_scroll, item_rect.Max - delta_scroll), in_flags);
13702 return delta_scroll;
13705float ImGui::GetScrollX()
13708 return window->Scroll.x;
13711float ImGui::GetScrollY()
13714 return window->Scroll.y;
13717float ImGui::GetScrollMaxX()
13720 return window->ScrollMax.x;
13723float ImGui::GetScrollMaxY()
13726 return window->ScrollMax.y;
13729void ImGui::SetScrollX(
ImGuiWindow *window,
float scroll_x)
13731 window->ScrollTarget.x = scroll_x;
13732 window->ScrollTargetCenterRatio.x = 0.0f;
13733 window->ScrollTargetEdgeSnapDist.x = 0.0f;
13736void ImGui::SetScrollY(
ImGuiWindow *window,
float scroll_y)
13738 window->ScrollTarget.y = scroll_y;
13739 window->ScrollTargetCenterRatio.y = 0.0f;
13740 window->ScrollTargetEdgeSnapDist.y = 0.0f;
13743void ImGui::SetScrollX(
float scroll_x)
13746 SetScrollX(g.CurrentWindow, scroll_x);
13749void ImGui::SetScrollY(
float scroll_y)
13752 SetScrollY(g.CurrentWindow, scroll_y);
13767void ImGui::SetScrollFromPosX(
ImGuiWindow *window,
float local_x,
float center_x_ratio)
13769 IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f);
13770 window->ScrollTarget.x = IM_TRUNC(local_x - window->DecoOuterSizeX1 - window->DecoInnerSizeX1 +
13772 window->ScrollTargetCenterRatio.x = center_x_ratio;
13773 window->ScrollTargetEdgeSnapDist.x = 0.0f;
13776void ImGui::SetScrollFromPosY(
ImGuiWindow *window,
float local_y,
float center_y_ratio)
13778 IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
13779 window->ScrollTarget.y = IM_TRUNC(local_y - window->DecoOuterSizeY1 - window->DecoInnerSizeY1 +
13781 window->ScrollTargetCenterRatio.y = center_y_ratio;
13782 window->ScrollTargetEdgeSnapDist.y = 0.0f;
13785void ImGui::SetScrollFromPosX(
float local_x,
float center_x_ratio)
13788 SetScrollFromPosX(g.CurrentWindow, local_x, center_x_ratio);
13791void ImGui::SetScrollFromPosY(
float local_y,
float center_y_ratio)
13794 SetScrollFromPosY(g.CurrentWindow, local_y, center_y_ratio);
13798void ImGui::SetScrollHereX(
float center_x_ratio)
13802 float spacing_x = ImMax(window->WindowPadding.x, g.Style.ItemSpacing.x);
13803 float target_pos_x =
13804 ImLerp(g.LastItemData.Rect.Min.x - spacing_x, g.LastItemData.Rect.Max.x + spacing_x, center_x_ratio);
13805 SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio);
13808 window->ScrollTargetEdgeSnapDist.x = ImMax(0.0f, window->WindowPadding.x - spacing_x);
13812void ImGui::SetScrollHereY(
float center_y_ratio)
13816 float spacing_y = ImMax(window->WindowPadding.y, g.Style.ItemSpacing.y);
13817 float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y,
13818 window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio);
13819 SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio);
13822 window->ScrollTargetEdgeSnapDist.y = ImMax(0.0f, window->WindowPadding.y - spacing_y);
13829bool ImGui::BeginTooltip()
13831 return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
13834bool ImGui::BeginItemTooltip()
13836 if (!IsItemHovered(ImGuiHoveredFlags_ForTooltip))
13838 return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
13841bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags)
13845 const bool is_dragdrop_tooltip = g.DragDropWithinSource || g.DragDropWithinTarget;
13846 if (is_dragdrop_tooltip)
13854 const bool is_touchscreen = (g.IO.MouseSource == ImGuiMouseSource_TouchScreen);
13855 if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos) == 0)
13857 ImVec2 tooltip_pos = is_touchscreen
13858 ? (g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_TOUCH * g.Style.MouseCursorScale)
13859 : (g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_MOUSE * g.Style.MouseCursorScale);
13860 ImVec2 tooltip_pivot = is_touchscreen ? TOOLTIP_DEFAULT_PIVOT_TOUCH :
ImVec2(0.0f, 0.0f);
13861 SetNextWindowPos(tooltip_pos, ImGuiCond_None, tooltip_pivot);
13864 SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f);
13867 tooltip_flags |= ImGuiTooltipFlags_OverridePrevious;
13870 const char *window_name_template = is_dragdrop_tooltip ?
"##Tooltip_DragDrop_%02d" :
"##Tooltip_%02d";
13871 char window_name[32];
13872 ImFormatString(window_name, IM_ARRAYSIZE(window_name), window_name_template, g.TooltipOverrideCount);
13873 if ((tooltip_flags & ImGuiTooltipFlags_OverridePrevious) && g.TooltipPreviousWindow != NULL &&
13874 g.TooltipPreviousWindow->Active)
13879 SetWindowHiddenAndSkipItemsForCurrentFrame(g.TooltipPreviousWindow);
13880 ImFormatString(window_name, IM_ARRAYSIZE(window_name), window_name_template, ++g.TooltipOverrideCount);
13883 ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar |
13884 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings |
13885 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking;
13886 Begin(window_name, NULL, flags | extra_window_flags);
13895void ImGui::EndTooltip()
13897 IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);
13901void ImGui::SetTooltip(
const char *fmt, ...)
13904 va_start(args, fmt);
13905 SetTooltipV(fmt, args);
13909void ImGui::SetTooltipV(
const char *fmt, va_list args)
13911 if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
13919void ImGui::SetItemTooltip(
const char *fmt, ...)
13922 va_start(args, fmt);
13923 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
13924 SetTooltipV(fmt, args);
13928void ImGui::SetItemTooltipV(
const char *fmt, va_list args)
13930 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
13931 SetTooltipV(fmt, args);
13939bool ImGui::IsPopupOpen(ImGuiID
id, ImGuiPopupFlags popup_flags)
13942 if (popup_flags & ImGuiPopupFlags_AnyPopupId)
13947 IM_ASSERT(
id == 0);
13948 if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
13949 return g.OpenPopupStack.Size > 0;
13951 return g.OpenPopupStack.Size > g.BeginPopupStack.Size;
13955 if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
13959 if (popup_data.PopupId == id)
13967 return g.OpenPopupStack.Size > g.BeginPopupStack.Size &&
13968 g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id;
13973bool ImGui::IsPopupOpen(
const char *str_id, ImGuiPopupFlags popup_flags)
13976 ImGuiID
id = (popup_flags & ImGuiPopupFlags_AnyPopupId) ? 0 : g.CurrentWindow->GetID(str_id);
13977 if ((popup_flags & ImGuiPopupFlags_AnyPopupLevel) &&
id != 0)
13979 0 &&
"Cannot use IsPopupOpen() with a string id and ImGuiPopupFlags_AnyPopupLevel.");
13982 return IsPopupOpen(
id, popup_flags);
13989 for (
int n = g.OpenPopupStack.Size - 1; n >= 0; n--)
13990 if (
ImGuiWindow *popup = g.OpenPopupStack.Data[n].Window)
13991 if (popup->Flags & ImGuiWindowFlags_Modal)
13997ImGuiWindow *ImGui::GetTopMostAndVisiblePopupModal()
14000 for (
int n = g.OpenPopupStack.Size - 1; n >= 0; n--)
14001 if (
ImGuiWindow *popup = g.OpenPopupStack.Data[n].Window)
14002 if ((popup->Flags & ImGuiWindowFlags_Modal) && IsWindowActiveAndVisible(popup))
14024 if (g.OpenPopupStack.Size <= 0)
14032 if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal))
14034 if (!popup_window->Active &&
14035 !popup_window->WasActive)
14040 return popup_window;
14041 if (IsWindowWithinBeginStackOf(window, popup_window))
14043 return popup_window;
14048void ImGui::OpenPopup(
const char *str_id, ImGuiPopupFlags popup_flags)
14051 ImGuiID
id = g.CurrentWindow->GetID(str_id);
14052 IMGUI_DEBUG_LOG_POPUP(
"[popup] OpenPopup(\"%s\" -> 0x%08X)\n", str_id,
id);
14053 OpenPopupEx(
id, popup_flags);
14056void ImGui::OpenPopup(ImGuiID
id, ImGuiPopupFlags popup_flags)
14058 OpenPopupEx(
id, popup_flags);
14066void ImGui::OpenPopupEx(ImGuiID
id, ImGuiPopupFlags popup_flags)
14070 const int current_stack_size = g.BeginPopupStack.Size;
14072 if (popup_flags & ImGuiPopupFlags_NoOpenOverExistingPopup)
14073 if (IsPopupOpen((ImGuiID)0, ImGuiPopupFlags_AnyPopupId))
14078 popup_ref.PopupId = id;
14079 popup_ref.Window = NULL;
14080 popup_ref.RestoreNavWindow =
14082 popup_ref.OpenFrameCount = g.FrameCount;
14083 popup_ref.OpenParentId = parent_window->IDStack.back();
14084 popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
14085 popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos;
14087 IMGUI_DEBUG_LOG_POPUP(
"[popup] OpenPopupEx(0x%08X)\n",
id);
14088 if (g.OpenPopupStack.Size < current_stack_size + 1)
14090 g.OpenPopupStack.push_back(popup_ref);
14099 bool keep_existing =
false;
14100 if (g.OpenPopupStack[current_stack_size].PopupId ==
id)
14101 if ((g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1) ||
14102 (popup_flags & ImGuiPopupFlags_NoReopen))
14103 keep_existing =
true;
14107 g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount;
14112 ClosePopupToLevel(current_stack_size,
true);
14113 g.OpenPopupStack.push_back(popup_ref);
14125void ImGui::ClosePopupsOverWindow(
ImGuiWindow *ref_window,
bool restore_focus_to_window_under_popup)
14128 if (g.OpenPopupStack.Size == 0)
14134 int popup_count_to_keep = 0;
14138 for (; popup_count_to_keep < g.OpenPopupStack.Size; popup_count_to_keep++)
14143 IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);
14154 bool ref_window_is_descendent_of_popup =
false;
14155 for (
int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++)
14156 if (
ImGuiWindow *popup_window = g.OpenPopupStack[n].Window)
14158 if (IsWindowWithinBeginStackOf(ref_window, popup_window))
14160 ref_window_is_descendent_of_popup =
true;
14163 if (!ref_window_is_descendent_of_popup)
14167 if (popup_count_to_keep <
14171 IMGUI_DEBUG_LOG_POPUP(
"[popup] ClosePopupsOverWindow(\"%s\")\n", ref_window ? ref_window->Name :
"<NULL>");
14172 ClosePopupToLevel(popup_count_to_keep, restore_focus_to_window_under_popup);
14176void ImGui::ClosePopupsExceptModals()
14180 int popup_count_to_keep;
14181 for (popup_count_to_keep = g.OpenPopupStack.Size; popup_count_to_keep > 0; popup_count_to_keep--)
14183 ImGuiWindow *window = g.OpenPopupStack[popup_count_to_keep - 1].Window;
14184 if (!window || (window->Flags & ImGuiWindowFlags_Modal))
14187 if (popup_count_to_keep <
14190 ClosePopupToLevel(popup_count_to_keep,
true);
14193void ImGui::ClosePopupToLevel(
int remaining,
bool restore_focus_to_window_under_popup)
14196 IMGUI_DEBUG_LOG_POPUP(
"[popup] ClosePopupToLevel(%d), restore_under=%d\n", remaining,
14197 restore_focus_to_window_under_popup);
14198 IM_ASSERT(remaining >= 0 && remaining < g.OpenPopupStack.Size);
14199 if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup)
14200 for (
int n = remaining; n < g.OpenPopupStack.Size; n++)
14201 IMGUI_DEBUG_LOG_POPUP(
"[popup] - Closing PopupID 0x%08X Window \"%s\"\n", g.OpenPopupStack[n].PopupId,
14202 g.OpenPopupStack[n].Window ? g.OpenPopupStack[n].Window->Name : NULL);
14206 g.OpenPopupStack.resize(remaining);
14210 if (restore_focus_to_window_under_popup && prev_popup.Window)
14213 ImGuiWindow *focus_window = (popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow
14214 : prev_popup.RestoreNavWindow;
14215 if (focus_window && !focus_window->WasActive)
14216 FocusTopMostWindowUnderOne(popup_window, NULL, NULL,
14217 ImGuiFocusRequestFlags_RestoreFocusedChild);
14219 FocusWindow(focus_window, (g.NavLayer == ImGuiNavLayer_Main) ? ImGuiFocusRequestFlags_RestoreFocusedChild
14220 : ImGuiFocusRequestFlags_None);
14225void ImGui::CloseCurrentPopup()
14228 int popup_idx = g.BeginPopupStack.Size - 1;
14229 if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size ||
14230 g.BeginPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId)
14234 while (popup_idx > 0)
14236 ImGuiWindow *popup_window = g.OpenPopupStack[popup_idx].Window;
14237 ImGuiWindow *parent_popup_window = g.OpenPopupStack[popup_idx - 1].Window;
14238 bool close_parent =
false;
14239 if (popup_window && (popup_window->Flags & ImGuiWindowFlags_ChildMenu))
14240 if (parent_popup_window && !(parent_popup_window->Flags & ImGuiWindowFlags_MenuBar))
14241 close_parent =
true;
14246 IMGUI_DEBUG_LOG_POPUP(
"[popup] CloseCurrentPopup %d -> %d\n", g.BeginPopupStack.Size - 1, popup_idx);
14247 ClosePopupToLevel(popup_idx,
true);
14253 window->DC.NavHideHighlightOneFrame =
true;
14257bool ImGui::BeginPopupEx(ImGuiID
id, ImGuiWindowFlags extra_window_flags)
14260 if (!IsPopupOpen(
id, ImGuiPopupFlags_None))
14262 g.NextWindowData.ClearFlags();
14267 IM_ASSERT((extra_window_flags & ImGuiWindowFlags_ChildMenu) == 0);
14268 ImFormatString(name, IM_ARRAYSIZE(name),
"##Popup_%08x",
14271 bool is_open = Begin(name, NULL, extra_window_flags | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoDocking);
14278bool ImGui::BeginPopupMenuEx(ImGuiID
id,
const char *label, ImGuiWindowFlags extra_window_flags)
14281 if (!IsPopupOpen(
id, ImGuiPopupFlags_None))
14283 g.NextWindowData.ClearFlags();
14288 IM_ASSERT(extra_window_flags & ImGuiWindowFlags_ChildMenu);
14289 ImFormatString(name, IM_ARRAYSIZE(name),
"%s###Menu_%02d", label,
14291 bool is_open = Begin(name, NULL, extra_window_flags | ImGuiWindowFlags_Popup);
14298bool ImGui::BeginPopup(
const char *str_id, ImGuiWindowFlags flags)
14301 if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size)
14303 g.NextWindowData.ClearFlags();
14306 flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings;
14307 ImGuiID
id = g.CurrentWindow->GetID(str_id);
14308 return BeginPopupEx(
id, flags);
14315bool ImGui::BeginPopupModal(
const char *name,
bool *p_open, ImGuiWindowFlags flags)
14319 const ImGuiID
id = window->GetID(name);
14320 if (!IsPopupOpen(
id, ImGuiPopupFlags_None))
14322 g.NextWindowData.ClearFlags();
14323 if (p_open && *p_open)
14332 if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos) == 0)
14336 : GetMainViewport();
14337 SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver,
ImVec2(0.5f, 0.5f));
14340 flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking;
14341 const bool is_open = Begin(name, p_open, flags);
14348 ClosePopupToLevel(g.BeginPopupStack.Size,
true);
14354void ImGui::EndPopup()
14358 if ((window->Flags & ImGuiWindowFlags_Popup) == 0 || g.BeginPopupStack.Size == 0)
14360 IM_ASSERT_USER_ERROR(0,
"Calling EndPopup() too many times or in wrong window!");
14366 if (g.NavWindow == window)
14367 NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);
14370 const ImGuiID backup_within_end_child_id = g.WithinEndChildID;
14371 if (window->Flags & ImGuiWindowFlags_ChildWindow)
14372 g.WithinEndChildID = window->ID;
14374 g.WithinEndChildID = backup_within_end_child_id;
14379void ImGui::OpenPopupOnItemClick(
const char *str_id, ImGuiPopupFlags popup_flags)
14383 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
14384 if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
14386 ImGuiID
id = str_id ? window->GetID(str_id)
14387 : g.LastItemData.ID;
14389 IM_ASSERT(
id != 0);
14390 OpenPopupEx(
id, popup_flags);
14412bool ImGui::BeginPopupContextItem(
const char *str_id, ImGuiPopupFlags popup_flags)
14416 if (window->SkipItems)
14419 str_id ? window->GetID(str_id) : g.LastItemData.ID;
14421 IM_ASSERT(
id != 0);
14422 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
14423 if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
14424 OpenPopupEx(
id, popup_flags);
14425 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar |
14426 ImGuiWindowFlags_NoSavedSettings);
14429bool ImGui::BeginPopupContextWindow(
const char *str_id, ImGuiPopupFlags popup_flags)
14434 str_id =
"window_context";
14435 ImGuiID
id = window->GetID(str_id);
14436 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
14437 if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
14438 if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
14439 OpenPopupEx(
id, popup_flags);
14440 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar |
14441 ImGuiWindowFlags_NoSavedSettings);
14444bool ImGui::BeginPopupContextVoid(
const char *str_id, ImGuiPopupFlags popup_flags)
14449 str_id =
"void_context";
14450 ImGuiID
id = window->GetID(str_id);
14451 int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
14452 if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
14453 if (GetTopMostPopupModal() == NULL)
14454 OpenPopupEx(
id, popup_flags);
14455 return BeginPopupEx(
id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar |
14456 ImGuiWindowFlags_NoSavedSettings);
14465ImVec2 ImGui::FindBestWindowPosForPopupEx(
const ImVec2 &ref_pos,
const ImVec2 &size, ImGuiDir *last_dir,
14466 const ImRect &r_outer,
const ImRect &r_avoid, ImGuiPopupPositionPolicy policy)
14468 ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size);
14473 if (policy == ImGuiPopupPositionPolicy_ComboBox)
14475 const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = {ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up};
14476 for (
int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
14478 const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
14479 if (n != -1 && dir == *last_dir)
14482 if (dir == ImGuiDir_Down)
14483 pos =
ImVec2(r_avoid.Min.x, r_avoid.Max.y);
14484 if (dir == ImGuiDir_Right)
14485 pos =
ImVec2(r_avoid.Min.x, r_avoid.Min.y - size.y);
14486 if (dir == ImGuiDir_Left)
14487 pos =
ImVec2(r_avoid.Max.x - size.x, r_avoid.Max.y);
14488 if (dir == ImGuiDir_Up)
14489 pos =
ImVec2(r_avoid.Max.x - size.x, r_avoid.Min.y - size.y);
14490 if (!r_outer.Contains(
ImRect(pos, pos + size)))
14499 if (policy == ImGuiPopupPositionPolicy_Tooltip || policy == ImGuiPopupPositionPolicy_Default)
14501 const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = {ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left};
14502 for (
int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
14504 const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
14505 if (n != -1 && dir == *last_dir)
14508 const float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) -
14509 (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x);
14510 const float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) -
14511 (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y);
14515 if (avail_w < size.x && (dir == ImGuiDir_Left || dir == ImGuiDir_Right))
14517 if (avail_h < size.y && (dir == ImGuiDir_Up || dir == ImGuiDir_Down))
14521 pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x
14522 : (dir == ImGuiDir_Right) ? r_avoid.Max.x
14523 : base_pos_clamped.x;
14524 pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y - size.y
14525 : (dir == ImGuiDir_Down) ? r_avoid.Max.y
14526 : base_pos_clamped.y;
14529 pos.x = ImMax(pos.x, r_outer.Min.x);
14530 pos.y = ImMax(pos.y, r_outer.Min.y);
14538 *last_dir = ImGuiDir_None;
14541 if (policy == ImGuiPopupPositionPolicy_Tooltip)
14542 return ref_pos +
ImVec2(2, 2);
14546 pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x);
14547 pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y);
14556 if (window->ViewportAllowPlatformMonitorExtend >= 0)
14559 const ImGuiPlatformMonitor &monitor = g.PlatformIO.Monitors[window->ViewportAllowPlatformMonitorExtend];
14560 r_screen.Min = monitor.WorkPos;
14561 r_screen.Max = monitor.WorkPos + monitor.WorkSize;
14566 r_screen = window->Viewport->GetMainRect();
14568 ImVec2 padding = g.Style.DisplaySafeAreaPadding;
14569 r_screen.Expand(
ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f,
14570 (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f));
14578 ImRect r_outer = GetPopupAllowedExtentRect(window);
14579 if (window->Flags & ImGuiWindowFlags_ChildMenu)
14584 ImGuiWindow *parent_window = window->ParentWindow;
14585 float horizontal_overlap =
14586 g.Style.ItemInnerSpacing.x;
14589 if (parent_window->DC.MenuBarAppending)
14591 ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX,
14592 parent_window->ClipRect.Max
14596 r_avoid =
ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX,
14597 parent_window->Pos.x + parent_window->Size.x - horizontal_overlap -
14598 parent_window->ScrollbarSizes.x,
14600 return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid,
14601 ImGuiPopupPositionPolicy_Default);
14603 if (window->Flags & ImGuiWindowFlags_Popup)
14605 return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer,
14606 ImRect(window->Pos, window->Pos),
14607 ImGuiPopupPositionPolicy_Default);
14609 if (window->Flags & ImGuiWindowFlags_Tooltip)
14620 IM_ASSERT(g.CurrentWindow == window);
14621 const float scale = g.Style.MouseCursorScale;
14622 const ImVec2 ref_pos = NavCalcPreferredRefPos();
14624 if (g.IO.MouseSource == ImGuiMouseSource_TouchScreen &&
14625 NavCalcPreferredRefPosSource() == ImGuiInputSource_Mouse)
14628 ref_pos + TOOLTIP_DEFAULT_OFFSET_TOUCH * scale - (TOOLTIP_DEFAULT_PIVOT_TOUCH * window->Size);
14629 if (r_outer.Contains(
ImRect(tooltip_pos, tooltip_pos + window->Size)))
14630 return tooltip_pos;
14633 ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_MOUSE * scale;
14635 if (g.NavCursorVisible && g.NavHighlightItemUnderNav && !g.IO.ConfigNavMoveSetMousePos)
14636 r_avoid =
ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
14638 r_avoid =
ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale,
14639 ref_pos.y + 24 * scale);
14643 return FindBestWindowPosForPopupEx(tooltip_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid,
14644 ImGuiPopupPositionPolicy_Tooltip);
14647 return window->Pos;
14666void ImGui::SetWindowFocus()
14668 FocusWindow(GImGui->CurrentWindow);
14671void ImGui::SetWindowFocus(
const char *name)
14675 if (
ImGuiWindow *window = FindWindowByName(name))
14676 FocusWindow(window);
14684void ImGui::SetNextWindowFocus()
14687 g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasFocus;
14691bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
14697 if (ref_window == NULL)
14699 if (flags & ImGuiFocusedFlags_AnyWindow)
14702 IM_ASSERT(cur_window);
14703 const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0;
14704 const bool dock_hierarchy = (flags & ImGuiFocusedFlags_DockHierarchy) != 0;
14705 if (flags & ImGuiHoveredFlags_RootWindow)
14706 cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
14708 if (flags & ImGuiHoveredFlags_ChildWindows)
14709 return IsWindowChildOf(ref_window, cur_window, popup_hierarchy, dock_hierarchy);
14711 return (ref_window == cur_window);
14714static int ImGui::FindWindowFocusIndex(
ImGuiWindow *window)
14718 int order = window->FocusOrder;
14719 IM_ASSERT(window->RootWindow == window);
14720 IM_ASSERT(g.WindowsFocusOrder[order] == window);
14724static void ImGui::UpdateWindowInFocusOrderList(
ImGuiWindow *window,
bool just_created, ImGuiWindowFlags new_flags)
14728 const bool new_is_explicit_child =
14729 (new_flags & ImGuiWindowFlags_ChildWindow) != 0 &&
14730 ((new_flags & ImGuiWindowFlags_Popup) == 0 || (new_flags & ImGuiWindowFlags_ChildMenu) != 0);
14731 const bool child_flag_changed = new_is_explicit_child != window->IsExplicitChild;
14732 if ((just_created || child_flag_changed) && !new_is_explicit_child)
14734 IM_ASSERT(!g.WindowsFocusOrder.contains(window));
14735 g.WindowsFocusOrder.push_back(window);
14736 window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1);
14738 else if (!just_created && child_flag_changed && new_is_explicit_child)
14740 IM_ASSERT(g.WindowsFocusOrder[window->FocusOrder] == window);
14741 for (
int n = window->FocusOrder + 1; n < g.WindowsFocusOrder.Size; n++)
14742 g.WindowsFocusOrder[n]->FocusOrder--;
14743 g.WindowsFocusOrder.erase(g.WindowsFocusOrder.Data + window->FocusOrder);
14744 window->FocusOrder = -1;
14746 window->IsExplicitChild = new_is_explicit_child;
14749void ImGui::BringWindowToFocusFront(
ImGuiWindow *window)
14752 IM_ASSERT(window == window->RootWindow);
14754 const int cur_order = window->FocusOrder;
14755 IM_ASSERT(g.WindowsFocusOrder[cur_order] == window);
14756 if (g.WindowsFocusOrder.back() == window)
14759 const int new_order = g.WindowsFocusOrder.Size - 1;
14760 for (
int n = cur_order; n < new_order; n++)
14762 g.WindowsFocusOrder[n] = g.WindowsFocusOrder[n + 1];
14763 g.WindowsFocusOrder[n]->FocusOrder--;
14764 IM_ASSERT(g.WindowsFocusOrder[n]->FocusOrder == n);
14766 g.WindowsFocusOrder[new_order] = window;
14767 window->FocusOrder = (short)new_order;
14771void ImGui::BringWindowToDisplayFront(
ImGuiWindow *window)
14774 ImGuiWindow *current_front_window = g.Windows.back();
14775 if (current_front_window == window ||
14776 current_front_window->RootWindowDockTree == window)
14778 for (
int i = g.Windows.Size - 2; i >= 0; i--)
14779 if (g.Windows[i] == window)
14781 memmove(&g.Windows[i], &g.Windows[i + 1], (
size_t)(g.Windows.Size - i - 1) *
sizeof(
ImGuiWindow *));
14782 g.Windows[g.Windows.Size - 1] = window;
14787void ImGui::BringWindowToDisplayBack(
ImGuiWindow *window)
14790 if (g.Windows[0] == window)
14792 for (
int i = 0; i < g.Windows.Size; i++)
14793 if (g.Windows[i] == window)
14795 memmove(&g.Windows[1], &g.Windows[0], (
size_t)i *
sizeof(
ImGuiWindow *));
14796 g.Windows[0] = window;
14803 IM_ASSERT(window != NULL && behind_window != NULL);
14805 window = window->RootWindow;
14806 behind_window = behind_window->RootWindow;
14807 int pos_wnd = FindWindowDisplayIndex(window);
14808 int pos_beh = FindWindowDisplayIndex(behind_window);
14809 if (pos_wnd < pos_beh)
14811 size_t copy_bytes = (pos_beh - pos_wnd - 1) *
sizeof(
ImGuiWindow *);
14812 memmove(&g.Windows.Data[pos_wnd], &g.Windows.Data[pos_wnd + 1], copy_bytes);
14813 g.Windows[pos_beh - 1] = window;
14817 size_t copy_bytes = (pos_wnd - pos_beh) *
sizeof(
ImGuiWindow *);
14818 memmove(&g.Windows.Data[pos_beh + 1], &g.Windows.Data[pos_beh], copy_bytes);
14819 g.Windows[pos_beh] = window;
14823int ImGui::FindWindowDisplayIndex(
ImGuiWindow *window)
14826 return g.Windows.index_from_ptr(g.Windows.find(window));
14830void ImGui::FocusWindow(
ImGuiWindow *window, ImGuiFocusRequestFlags flags)
14835 if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window))
14836 if (
ImGuiWindow *blocking_modal = FindBlockingModal(window))
14841 IMGUI_DEBUG_LOG_FOCUS(
"[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n",
14842 window ? window->Name :
"<NULL>", blocking_modal->Name);
14843 if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
14844 BringWindowToDisplayBehind(
14845 window, blocking_modal);
14846 ClosePopupsOverWindow(GetTopMostPopupModal(),
false);
14852 if ((flags & ImGuiFocusRequestFlags_RestoreFocusedChild) && window != NULL)
14853 window = NavRestoreLastChildNavWindow(window);
14856 if (g.NavWindow != window)
14858 SetNavWindow(window);
14859 if (window && g.NavHighlightItemUnderNav)
14860 g.NavMousePosDirty =
true;
14861 g.NavId = window ? window->NavLastIds[0] : 0;
14862 g.NavLayer = ImGuiNavLayer_Main;
14863 SetNavFocusScope(window ? window->NavRootFocusScopeId : 0);
14864 g.NavIdIsAlive =
false;
14865 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
14868 ClosePopupsOverWindow(window,
false);
14872 IM_ASSERT(window == NULL || window->RootWindowDockTree != NULL);
14873 ImGuiWindow *focus_front_window = window ? window->RootWindow : NULL;
14874 ImGuiWindow *display_front_window = window ? window->RootWindowDockTree : NULL;
14875 ImGuiDockNode *dock_node = window ? window->DockNode : NULL;
14876 bool active_id_window_is_dock_node_host =
14877 (g.ActiveIdWindow && dock_node && dock_node->HostWindow == g.ActiveIdWindow);
14886 if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window)
14887 if (!g.ActiveIdNoClearOnFocusLoss && !active_id_window_is_dock_node_host)
14893 window->LastFrameJustFocused = g.FrameCount;
14901 BringWindowToFocusFront(focus_front_window);
14902 if (((window->Flags | focus_front_window->Flags | display_front_window->Flags) &
14903 ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
14904 BringWindowToDisplayFront(display_front_window);
14908 ImGuiViewport *filter_viewport, ImGuiFocusRequestFlags flags)
14911 int start_idx = g.WindowsFocusOrder.Size - 1;
14912 if (under_this_window != NULL)
14916 while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow)
14918 under_this_window = under_this_window->ParentWindow;
14921 start_idx = FindWindowFocusIndex(under_this_window) + offset;
14923 for (
int i = start_idx; i >= 0; i--)
14928 if (window == ignore_window || !window->WasActive)
14930 if (filter_viewport != NULL && window->Viewport != filter_viewport)
14932 if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) !=
14933 (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
14942 FocusWindow(window, flags);
14946 FocusWindow(NULL, flags);
14957void ImGui::SetNavCursorVisible(
bool visible)
14960 if (g.IO.ConfigNavCursorVisibleAlways)
14962 g.NavCursorVisible = visible;
14966void ImGui::SetNavCursorVisibleAfterMove()
14969 if (g.IO.ConfigNavCursorVisibleAuto)
14970 g.NavCursorVisible =
true;
14971 g.NavHighlightItemUnderNav = g.NavMousePosDirty =
true;
14977 if (g.NavWindow != window)
14979 IMGUI_DEBUG_LOG_FOCUS(
"[focus] SetNavWindow(\"%s\")\n", window ? window->Name :
"<NULL>");
14980 g.NavWindow = window;
14981 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
14983 g.NavInitRequest = g.NavMoveSubmitted = g.NavMoveScoringItems =
false;
14984 NavUpdateAnyRequestFlag();
14987void ImGui::NavHighlightActivated(ImGuiID
id)
14990 g.NavHighlightActivatedId = id;
14991 g.NavHighlightActivatedTimer = NAV_ACTIVATE_HIGHLIGHT_TIMER;
14994void ImGui::NavClearPreferredPosForAxis(ImGuiAxis axis)
14997 g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer][axis] = FLT_MAX;
15000void ImGui::SetNavID(ImGuiID
id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id,
const ImRect &rect_rel)
15003 IM_ASSERT(g.NavWindow != NULL);
15004 IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu);
15006 g.NavLayer = nav_layer;
15007 SetNavFocusScope(focus_scope_id);
15008 g.NavWindow->NavLastIds[nav_layer] = id;
15009 g.NavWindow->NavRectRel[nav_layer] = rect_rel;
15012 NavClearPreferredPosForAxis(ImGuiAxis_X);
15013 NavClearPreferredPosForAxis(ImGuiAxis_Y);
15016void ImGui::SetFocusID(ImGuiID
id,
ImGuiWindow *window)
15019 IM_ASSERT(
id != 0);
15021 if (g.NavWindow != window)
15022 SetNavWindow(window);
15026 const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent;
15028 g.NavLayer = nav_layer;
15029 SetNavFocusScope(g.CurrentFocusScopeId);
15030 window->NavLastIds[nav_layer] = id;
15031 if (g.LastItemData.ID ==
id)
15032 window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
15034 if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
15035 g.NavHighlightItemUnderNav =
true;
15036 else if (g.IO.ConfigNavCursorVisibleAuto)
15037 g.NavCursorVisible =
false;
15040 NavClearPreferredPosForAxis(ImGuiAxis_X);
15041 NavClearPreferredPosForAxis(ImGuiAxis_Y);
15044static ImGuiDir ImGetDirQuadrantFromDelta(
float dx,
float dy)
15046 if (ImFabs(dx) > ImFabs(dy))
15047 return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left;
15048 return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
15051static float inline NavScoreItemDistInterval(
float cand_min,
float cand_max,
float curr_min,
float curr_max)
15053 if (cand_max < curr_min)
15054 return cand_max - curr_min;
15055 if (curr_max < cand_min)
15056 return cand_min - curr_max;
15065 if (g.NavLayer != window->DC.NavLayerCurrent)
15069 ImRect cand = g.LastItemData.NavRect;
15070 const ImRect curr = g.NavScoringRect;
15072 g.NavScoringDebugCount++;
15075 if (window->ParentWindow == g.NavWindow)
15077 IM_ASSERT((window->ChildFlags | g.NavWindow->ChildFlags) & ImGuiChildFlags_NavFlattened);
15078 if (!window->ClipRect.Overlaps(cand))
15086 float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
15087 float dby = NavScoreItemDistInterval(
15088 ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f),
15089 ImLerp(curr.Min.y, curr.Max.y, 0.2f),
15090 ImLerp(curr.Min.y, curr.Max.y,
15092 if (dby != 0.0f && dbx != 0.0f)
15093 dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
15094 float dist_box = ImFabs(dbx) + ImFabs(dby);
15098 float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x);
15099 float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y);
15100 float dist_center = ImFabs(dcx) + ImFabs(dcy);
15104 float dax = 0.0f, day = 0.0f, dist_axial = 0.0f;
15105 if (dbx != 0.0f || dby != 0.0f)
15115 dist_axial = dist_box;
15116 quadrant = ImGetDirQuadrantFromDelta(dbx, dby);
15118 else if (dcx != 0.0f || dcy != 0.0f)
15123 dist_axial = dist_center;
15124 quadrant = ImGetDirQuadrantFromDelta(dcx, dcy);
15130 quadrant = (g.LastItemData.ID < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
15133 const ImGuiDir move_dir = g.NavMoveDir;
15134#if IMGUI_DEBUG_NAV_SCORING
15138 if (quadrant == move_dir)
15140 ImFormatString(buf, IM_ARRAYSIZE(buf),
"%.0f/%.0f", dist_box, dist_center);
15141 ImDrawList *draw_list = GetForegroundDrawList(window);
15142 draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 80));
15143 draw_list->AddRectFilled(cand.Min, cand.Min + CalcTextSize(buf), IM_COL32(255, 0, 0, 200));
15144 draw_list->AddText(cand.Min, IM_COL32(255, 255, 255, 255), buf);
15147 const bool debug_hovering = IsMouseHoveringRect(cand.Min, cand.Max);
15148 const bool debug_tty = (g.IO.KeyCtrl &&
IsKeyPressed(ImGuiKey_Space));
15149 if (debug_hovering || debug_tty)
15151 ImFormatString(buf, IM_ARRAYSIZE(buf),
15152 "d-box (%7.3f,%7.3f) -> %7.3f\nd-center (%7.3f,%7.3f) -> %7.3f\nd-axial (%7.3f,%7.3f) -> "
15153 "%7.3f\nnav %c, quadrant %c",
15154 dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial,
"-WENS"[move_dir + 1],
15155 "-WENS"[quadrant + 1]);
15156 if (debug_hovering)
15158 ImDrawList *draw_list = GetForegroundDrawList(window);
15159 draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255, 200, 0, 100));
15160 draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255, 255, 0, 200));
15161 draw_list->AddRectFilled(cand.Max -
ImVec2(4, 4), cand.Max + CalcTextSize(buf) +
ImVec2(4, 4),
15162 IM_COL32(40, 0, 0, 200));
15163 draw_list->AddText(cand.Max, ~0U, buf);
15167 IMGUI_DEBUG_LOG_NAV(
"id 0x%08X\n%s\n", g.LastItemData.ID, buf);
15173 bool new_best =
false;
15174 if (quadrant == move_dir)
15177 if (dist_box < result->DistBox)
15179 result->DistBox = dist_box;
15180 result->DistCenter = dist_center;
15183 if (dist_box == result->DistBox)
15186 if (dist_center < result->DistCenter)
15188 result->DistCenter = dist_center;
15191 else if (dist_center == result->DistCenter)
15198 if (((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) ? dby : dbx) <
15213 if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial)
15214 if (g.NavLayer == ImGuiNavLayer_Menu && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
15215 if ((move_dir == ImGuiDir_Left && dax < 0.0f) || (move_dir == ImGuiDir_Right && dax > 0.0f) ||
15216 (move_dir == ImGuiDir_Up && day < 0.0f) || (move_dir == ImGuiDir_Down && day > 0.0f))
15218 result->DistAxial = dist_axial;
15229 result->Window = window;
15230 result->ID = g.LastItemData.ID;
15231 result->FocusScopeId = g.CurrentFocusScopeId;
15232 result->ItemFlags = g.LastItemData.ItemFlags;
15233 result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
15234 if (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData)
15236 IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
15237 result->SelectionUserData =
15238 g.NextItemData.SelectionUserData;
15245void ImGui::NavUpdateCurrentWindowIsScrollPushableX()
15249 window->DC.NavIsScrollPushableX = (g.CurrentTable == NULL && window->DC.CurrentColumns == NULL);
15254static void ImGui::NavProcessItem()
15258 const ImGuiID
id = g.LastItemData.ID;
15259 const ImGuiItemFlags item_flags = g.LastItemData.ItemFlags;
15262 if (window->DC.NavIsScrollPushableX ==
false)
15264 g.LastItemData.NavRect.Min.x =
15265 ImClamp(g.LastItemData.NavRect.Min.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
15266 g.LastItemData.NavRect.Max.x =
15267 ImClamp(g.LastItemData.NavRect.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x);
15269 const ImRect nav_bb = g.LastItemData.NavRect;
15272 if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent && (item_flags & ImGuiItemFlags_Disabled) == 0)
15276 const bool candidate_for_nav_default_focus = (item_flags & ImGuiItemFlags_NoNavDefaultFocus) == 0;
15277 if (candidate_for_nav_default_focus || g.NavInitResult.ID == 0)
15279 NavApplyItemToResult(&g.NavInitResult);
15281 if (candidate_for_nav_default_focus)
15283 g.NavInitRequest =
false;
15284 NavUpdateAnyRequestFlag();
15291 if (g.NavMoveScoringItems && (item_flags & ImGuiItemFlags_Disabled) == 0)
15293 if ((g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi) || (window->Flags & ImGuiWindowFlags_NoNavInputs) == 0)
15295 const bool is_tabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0;
15298 NavProcessItemForTabbingRequest(
id, item_flags, g.NavMoveFlags);
15300 else if (g.NavId !=
id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId))
15302 ImGuiNavItemData *result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
15303 if (NavScoreItem(result))
15304 NavApplyItemToResult(result);
15307 const float VISIBLE_RATIO = 0.70f;
15308 if ((g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
15309 if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) -
15310 ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >=
15311 (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO)
15312 if (NavScoreItem(&g.NavMoveResultLocalVisible))
15313 NavApplyItemToResult(&g.NavMoveResultLocalVisible);
15321 if (g.NavWindow != window)
15322 SetNavWindow(window);
15324 g.NavLayer = window->DC.NavLayerCurrent;
15325 SetNavFocusScope(g.CurrentFocusScopeId);
15326 g.NavFocusScopeId = g.CurrentFocusScopeId;
15327 g.NavIdIsAlive =
true;
15328 if (g.LastItemData.ItemFlags & ImGuiItemFlags_HasSelectionUserData)
15330 IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
15331 g.NavLastValidSelectionUserData =
15332 g.NextItemData.SelectionUserData;
15335 window->NavRectRel[window->DC.NavLayerCurrent] =
15336 WindowRectAbsToRel(window, nav_bb);
15349void ImGui::NavProcessItemForTabbingRequest(ImGuiID
id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags)
15353 if ((move_flags & ImGuiNavMoveFlags_FocusApi) == 0)
15355 if (g.NavLayer != g.CurrentWindow->DC.NavLayerCurrent)
15357 if (g.NavFocusScopeId != g.CurrentFocusScopeId)
15365 if (move_flags & ImGuiNavMoveFlags_FocusApi)
15368 can_stop = (item_flags & ImGuiItemFlags_NoTabStop) == 0 &&
15369 ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) || (item_flags & ImGuiItemFlags_Inputable));
15374 if (g.NavTabbingDir == +1)
15377 if (can_stop && g.NavTabbingResultFirst.ID == 0)
15378 NavApplyItemToResult(&g.NavTabbingResultFirst);
15379 if (can_stop && g.NavTabbingCounter > 0 && --g.NavTabbingCounter == 0)
15380 NavMoveRequestResolveWithLastItem(result);
15381 else if (g.NavId ==
id)
15382 g.NavTabbingCounter = 1;
15384 else if (g.NavTabbingDir == -1)
15391 g.NavMoveScoringItems =
false;
15392 NavUpdateAnyRequestFlag();
15398 NavApplyItemToResult(result);
15401 else if (g.NavTabbingDir == 0)
15403 if (can_stop && g.NavId ==
id)
15404 NavMoveRequestResolveWithLastItem(result);
15405 if (can_stop && g.NavTabbingResultFirst.ID == 0)
15406 NavApplyItemToResult(&g.NavTabbingResultFirst);
15410bool ImGui::NavMoveRequestButNoResultYet()
15413 return g.NavMoveScoringItems && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0;
15417void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags,
15418 ImGuiScrollFlags scroll_flags)
15421 IM_ASSERT(g.NavWindow != NULL);
15425 if (move_flags & ImGuiNavMoveFlags_IsTabbing)
15426 move_flags |= ImGuiNavMoveFlags_AllowCurrentNavId;
15428 g.NavMoveSubmitted = g.NavMoveScoringItems =
true;
15429 g.NavMoveDir = move_dir;
15430 g.NavMoveDirForDebug = move_dir;
15431 g.NavMoveClipDir = clip_dir;
15432 g.NavMoveFlags = move_flags;
15433 g.NavMoveScrollFlags = scroll_flags;
15434 g.NavMoveForwardToNextFrame =
false;
15435 g.NavMoveKeyMods = (move_flags & ImGuiNavMoveFlags_FocusApi) ? 0 : g.IO.KeyMods;
15436 g.NavMoveResultLocal.Clear();
15437 g.NavMoveResultLocalVisible.Clear();
15438 g.NavMoveResultOther.Clear();
15439 g.NavTabbingCounter = 0;
15440 g.NavTabbingResultFirst.Clear();
15441 NavUpdateAnyRequestFlag();
15447 g.NavMoveScoringItems =
false;
15448 NavApplyItemToResult(result);
15449 NavUpdateAnyRequestFlag();
15456 g.NavMoveScoringItems =
false;
15457 g.LastItemData.ID = tree_node_data->ID;
15458 g.LastItemData.ItemFlags =
15459 tree_node_data->ItemFlags &
15460 ~ImGuiItemFlags_HasSelectionUserData;
15461 g.LastItemData.NavRect = tree_node_data->NavRect;
15462 NavApplyItemToResult(result);
15463 NavClearPreferredPosForAxis(ImGuiAxis_Y);
15464 NavUpdateAnyRequestFlag();
15467void ImGui::NavMoveRequestCancel()
15470 g.NavMoveSubmitted = g.NavMoveScoringItems =
false;
15471 NavUpdateAnyRequestFlag();
15475void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags,
15476 ImGuiScrollFlags scroll_flags)
15479 IM_ASSERT(g.NavMoveForwardToNextFrame ==
false);
15480 NavMoveRequestCancel();
15481 g.NavMoveForwardToNextFrame =
true;
15482 g.NavMoveDir = move_dir;
15483 g.NavMoveClipDir = clip_dir;
15484 g.NavMoveFlags = move_flags | ImGuiNavMoveFlags_Forwarded;
15485 g.NavMoveScrollFlags = scroll_flags;
15490void ImGui::NavMoveRequestTryWrapping(
ImGuiWindow *window, ImGuiNavMoveFlags wrap_flags)
15493 IM_ASSERT((wrap_flags & ImGuiNavMoveFlags_WrapMask_) != 0 &&
15494 (wrap_flags & ~ImGuiNavMoveFlags_WrapMask_) == 0);
15498 if (g.NavWindow == window && g.NavMoveScoringItems && g.NavLayer == ImGuiNavLayer_Main)
15499 g.NavMoveFlags = (g.NavMoveFlags & ~ImGuiNavMoveFlags_WrapMask_) | wrap_flags;
15504static void ImGui::NavSaveLastChildNavWindowIntoParent(
ImGuiWindow *nav_window)
15507 while (parent && parent->RootWindow != parent &&
15508 (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
15509 parent = parent->ParentWindow;
15510 if (parent && parent != nav_window)
15511 parent->NavLastChildNavWindow = nav_window;
15518 if (window->NavLastChildNavWindow && window->NavLastChildNavWindow->WasActive)
15519 return window->NavLastChildNavWindow;
15520 if (window->DockNodeAsHost && window->DockNodeAsHost->TabBar)
15521 if (
ImGuiTabItem *tab = TabBarFindMostRecentlySelectedTabForActiveWindow(window->DockNodeAsHost->TabBar))
15522 return tab->Window;
15526void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
15529 if (layer == ImGuiNavLayer_Main)
15532 g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow);
15533 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
15534 if (prev_nav_window)
15535 IMGUI_DEBUG_LOG_FOCUS(
"[focus] NavRestoreLayer: from \"%s\" to SetNavWindow(\"%s\")\n",
15536 prev_nav_window->Name, g.NavWindow->Name);
15539 if (window->NavLastIds[layer] != 0)
15541 SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
15545 g.NavLayer = layer;
15546 NavInitWindow(window,
true);
15550static inline void ImGui::NavUpdateAnyRequestFlag()
15553 g.NavAnyRequest = g.NavMoveScoringItems || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL);
15554 if (g.NavAnyRequest)
15555 IM_ASSERT(g.NavWindow != NULL);
15559void ImGui::NavInitWindow(
ImGuiWindow *window,
bool force_reinit)
15563 IM_ASSERT(window == g.NavWindow);
15565 if (window->Flags & ImGuiWindowFlags_NoNavInputs)
15568 SetNavFocusScope(window->NavRootFocusScopeId);
15572 bool init_for_nav =
false;
15573 if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) ||
15575 init_for_nav =
true;
15576 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n",
15577 init_for_nav, window->Name, g.NavLayer);
15580 SetNavID(0, g.NavLayer, window->NavRootFocusScopeId,
ImRect());
15581 g.NavInitRequest =
true;
15582 g.NavInitRequestFromMove =
false;
15583 g.NavInitResult.ID = 0;
15584 NavUpdateAnyRequestFlag();
15588 g.NavId = window->NavLastIds[0];
15589 SetNavFocusScope(window->NavRootFocusScopeId);
15593static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource()
15597 const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
15601 if ((!g.NavCursorVisible || !g.NavHighlightItemUnderNav || !window) && !activated_shortcut)
15602 return ImGuiInputSource_Mouse;
15604 return ImGuiInputSource_Keyboard;
15607static ImVec2 ImGui::NavCalcPreferredRefPos()
15611 ImGuiInputSource source = NavCalcPreferredRefPosSource();
15613 const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
15617 if (source == ImGuiInputSource_Mouse)
15623 ImVec2 p = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : g.MouseLastValidPos;
15624 return ImVec2(p.x + 1.0f, p.y);
15631 if (activated_shortcut)
15632 ref_rect = g.LastItemData.NavRect;
15634 ref_rect = WindowRectRelToAbs(window, window->NavRectRel[g.NavLayer]);
15637 if (window->LastFrameActive != g.FrameCount &&
15638 (window->ScrollTarget.x != FLT_MAX || window->ScrollTarget.y != FLT_MAX))
15640 ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
15641 ref_rect.Translate(window->Scroll - next_scroll);
15643 ImVec2 pos =
ImVec2(ref_rect.Min.x + ImMin(g.Style.FramePadding.x * 4, ref_rect.GetWidth()),
15644 ref_rect.Max.y - ImMin(g.Style.FramePadding.y, ref_rect.GetHeight()));
15646 return ImTrunc(ImClamp(
15647 pos, viewport->Pos,
15648 viewport->Pos + viewport->Size));
15653float ImGui::GetNavTweakPressedAmount(ImGuiAxis axis)
15656 float repeat_delay, repeat_rate;
15657 GetTypematicRepeatRate(ImGuiInputFlags_RepeatRateNavTweak, &repeat_delay, &repeat_rate);
15659 ImGuiKey key_less, key_more;
15660 if (g.NavInputSource == ImGuiInputSource_Gamepad)
15662 key_less = (axis == ImGuiAxis_X) ? ImGuiKey_GamepadDpadLeft : ImGuiKey_GamepadDpadUp;
15663 key_more = (axis == ImGuiAxis_X) ? ImGuiKey_GamepadDpadRight : ImGuiKey_GamepadDpadDown;
15667 key_less = (axis == ImGuiAxis_X) ? ImGuiKey_LeftArrow : ImGuiKey_UpArrow;
15668 key_more = (axis == ImGuiAxis_X) ? ImGuiKey_RightArrow : ImGuiKey_DownArrow;
15670 float amount = (float)GetKeyPressedAmount(key_more, repeat_delay, repeat_rate) -
15671 (float)GetKeyPressedAmount(key_less, repeat_delay, repeat_rate);
15672 if (amount != 0.0f &&
IsKeyDown(key_less) &&
15678static void ImGui::NavUpdate()
15683 io.WantSetMousePos =
false;
15691 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 &&
15692 (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
15693 const ImGuiKey nav_gamepad_keys_to_change_source[] = {
15694 ImGuiKey_GamepadFaceRight, ImGuiKey_GamepadFaceLeft, ImGuiKey_GamepadFaceUp, ImGuiKey_GamepadFaceDown,
15695 ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown};
15696 if (nav_gamepad_active)
15697 for (ImGuiKey key : nav_gamepad_keys_to_change_source)
15699 g.NavInputSource = ImGuiInputSource_Gamepad;
15700 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
15701 const ImGuiKey nav_keyboard_keys_to_change_source[] = {ImGuiKey_Space, ImGuiKey_Enter, ImGuiKey_Escape,
15702 ImGuiKey_RightArrow, ImGuiKey_LeftArrow, ImGuiKey_UpArrow,
15703 ImGuiKey_DownArrow};
15704 if (nav_keyboard_active)
15705 for (ImGuiKey key : nav_keyboard_keys_to_change_source)
15707 g.NavInputSource = ImGuiInputSource_Keyboard;
15710 g.NavJustMovedToId = 0;
15711 g.NavJustMovedToFocusScopeId = g.NavJustMovedFromFocusScopeId = 0;
15712 if (g.NavInitResult.ID != 0)
15713 NavInitRequestApplyResult();
15714 g.NavInitRequest =
false;
15715 g.NavInitRequestFromMove =
false;
15716 g.NavInitResult.ID = 0;
15719 if (g.NavMoveSubmitted)
15720 NavMoveRequestApplyResult();
15721 g.NavTabbingCounter = 0;
15722 g.NavMoveSubmitted = g.NavMoveScoringItems =
false;
15723 if (g.NavCursorHideFrames > 0)
15724 if (--g.NavCursorHideFrames == 0)
15725 g.NavCursorVisible =
true;
15729 bool set_mouse_pos =
false;
15730 if (g.NavMousePosDirty && g.NavIdIsAlive)
15731 if (g.NavCursorVisible && g.NavHighlightItemUnderNav && g.NavWindow)
15732 set_mouse_pos =
true;
15733 g.NavMousePosDirty =
false;
15734 IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu);
15739 NavSaveLastChildNavWindowIntoParent(g.NavWindow);
15740 if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == ImGuiNavLayer_Main)
15741 g.NavWindow->NavLastChildNavWindow = NULL;
15744 NavUpdateWindowing();
15747 io.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow &&
15748 !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
15749 io.NavVisible = (io.NavActive && g.NavId != 0 && g.NavCursorVisible) || (g.NavWindowingTarget != NULL);
15752 NavUpdateCancelRequest();
15755 g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0;
15756 g.NavActivateFlags = ImGuiActivateFlags_None;
15757 if (g.NavId != 0 && g.NavCursorVisible && !g.NavWindowingTarget && g.NavWindow &&
15758 !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
15760 const bool activate_down =
15761 (nav_keyboard_active &&
IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_NoOwner)) ||
15762 (nav_gamepad_active &&
IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_NoOwner));
15763 const bool activate_pressed =
15765 ((nav_keyboard_active &&
IsKeyPressed(ImGuiKey_Space, 0, ImGuiKeyOwner_NoOwner)) ||
15766 (nav_gamepad_active &&
IsKeyPressed(ImGuiKey_NavGamepadActivate, 0, ImGuiKeyOwner_NoOwner)));
15767 const bool input_down = (nav_keyboard_active && (
IsKeyDown(ImGuiKey_Enter, ImGuiKeyOwner_NoOwner) ||
15768 IsKeyDown(ImGuiKey_KeypadEnter, ImGuiKeyOwner_NoOwner))) ||
15769 (nav_gamepad_active &&
IsKeyDown(ImGuiKey_NavGamepadInput, ImGuiKeyOwner_NoOwner));
15770 const bool input_pressed =
15771 input_down && ((nav_keyboard_active && (
IsKeyPressed(ImGuiKey_Enter, 0, ImGuiKeyOwner_NoOwner) ||
15772 IsKeyPressed(ImGuiKey_KeypadEnter, 0, ImGuiKeyOwner_NoOwner))) ||
15773 (nav_gamepad_active &&
IsKeyPressed(ImGuiKey_NavGamepadInput, 0, ImGuiKeyOwner_NoOwner)));
15774 if (g.ActiveId == 0 && activate_pressed)
15776 g.NavActivateId = g.NavId;
15777 g.NavActivateFlags = ImGuiActivateFlags_PreferTweak;
15779 if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && input_pressed)
15781 g.NavActivateId = g.NavId;
15782 g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
15784 if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_down || input_down))
15785 g.NavActivateDownId = g.NavId;
15786 if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_pressed || input_pressed))
15788 g.NavActivatePressedId = g.NavId;
15789 NavHighlightActivated(g.NavId);
15792 if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
15793 g.NavCursorVisible =
false;
15794 else if (g.IO.ConfigNavCursorVisibleAlways && g.NavCursorHideFrames == 0)
15795 g.NavCursorVisible =
true;
15796 if (g.NavActivateId != 0)
15797 IM_ASSERT(g.NavActivateDownId == g.NavActivateId);
15800 if (g.NavHighlightActivatedTimer > 0.0f)
15801 g.NavHighlightActivatedTimer = ImMax(0.0f, g.NavHighlightActivatedTimer - io.DeltaTime);
15802 if (g.NavHighlightActivatedTimer == 0.0f)
15803 g.NavHighlightActivatedId = 0;
15807 if (g.NavNextActivateId != 0)
15809 g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavNextActivateId;
15810 g.NavActivateFlags = g.NavNextActivateFlags;
15812 g.NavNextActivateId = 0;
15815 NavUpdateCreateMoveRequest();
15816 if (g.NavMoveDir == ImGuiDir_None)
15817 NavUpdateCreateTabbingRequest();
15818 NavUpdateAnyRequestFlag();
15819 g.NavIdIsAlive =
false;
15822 if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget)
15826 const float scroll_speed = IM_ROUND(
15827 window->FontRefSize * 100 *
15829 const ImGuiDir move_dir = g.NavMoveDir;
15830 if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY && move_dir != ImGuiDir_None)
15832 if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
15834 ImTrunc(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
15835 if (move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down)
15837 ImTrunc(window->Scroll.y + ((move_dir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
15843 if (nav_gamepad_active)
15845 const ImVec2 scroll_dir = GetKeyMagnitude2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight,
15846 ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown);
15847 const float tweak_factor =
IsKeyDown(ImGuiKey_NavGamepadTweakSlow) ? 1.0f / 10.0f
15848 :
IsKeyDown(ImGuiKey_NavGamepadTweakFast) ? 10.0f
15850 if (scroll_dir.x != 0.0f && window->ScrollbarX)
15851 SetScrollX(window, ImTrunc(window->Scroll.x + scroll_dir.x * scroll_speed * tweak_factor));
15852 if (scroll_dir.y != 0.0f)
15853 SetScrollY(window, ImTrunc(window->Scroll.y + scroll_dir.y * scroll_speed * tweak_factor));
15858 if (!nav_keyboard_active && !nav_gamepad_active)
15860 g.NavCursorVisible =
false;
15861 g.NavHighlightItemUnderNav = set_mouse_pos =
false;
15867 if (set_mouse_pos && io.ConfigNavMoveSetMousePos && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
15868 TeleportMousePos(NavCalcPreferredRefPos());
15871 g.NavScoringDebugCount = 0;
15872#if IMGUI_DEBUG_NAV_RECTS
15875 ImDrawList *draw_list = GetForegroundDrawList(debug_window);
15876 int layer = g.NavLayer;
15878 ImRect r = WindowRectRelToAbs(debug_window, debug_window->NavRectRel[layer]);
15879 draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 200, 0, 255));
15888void ImGui::NavInitRequestApplyResult()
15897 if (g.NavId != result->ID)
15899 g.NavJustMovedFromFocusScopeId = g.NavFocusScopeId;
15900 g.NavJustMovedToId = result->ID;
15901 g.NavJustMovedToFocusScopeId = result->FocusScopeId;
15902 g.NavJustMovedToKeyMods = 0;
15903 g.NavJustMovedToIsTabbing =
false;
15904 g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
15911 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: ApplyResult: NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID,
15912 g.NavLayer, g.NavWindow->Name);
15913 SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
15914 g.NavIdIsAlive =
true;
15915 if (result->SelectionUserData != ImGuiSelectionUserData_Invalid)
15916 g.NavLastValidSelectionUserData = result->SelectionUserData;
15917 if (g.NavInitRequestFromMove)
15918 SetNavCursorVisibleAfterMove();
15922static void NavBiasScoringRect(
ImRect &r,
ImVec2 &preferred_pos_rel, ImGuiDir move_dir, ImGuiNavMoveFlags move_flags)
15926 const ImVec2 rel_to_abs_offset = g.NavWindow->DC.CursorStartPos;
15932 if ((move_flags & ImGuiNavMoveFlags_Forwarded) == 0)
15934 if (preferred_pos_rel.x == FLT_MAX)
15935 preferred_pos_rel.x = ImMin(r.Min.x + 1.0f, r.Max.x) - rel_to_abs_offset.x;
15936 if (preferred_pos_rel.y == FLT_MAX)
15937 preferred_pos_rel.y = r.GetCenter().y - rel_to_abs_offset.y;
15941 if ((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) && preferred_pos_rel.x != FLT_MAX)
15942 r.Min.x = r.Max.x = preferred_pos_rel.x + rel_to_abs_offset.x;
15943 else if ((move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) && preferred_pos_rel.y != FLT_MAX)
15944 r.Min.y = r.Max.y = preferred_pos_rel.y + rel_to_abs_offset.y;
15947void ImGui::NavUpdateCreateMoveRequest()
15952 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 &&
15953 (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
15954 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
15956 if (g.NavMoveForwardToNextFrame && window != NULL)
15961 IM_ASSERT(g.NavMoveDir != ImGuiDir_None && g.NavMoveClipDir != ImGuiDir_None);
15962 IM_ASSERT(g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded);
15963 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequestForward %d\n", g.NavMoveDir);
15968 g.NavMoveDir = ImGuiDir_None;
15969 g.NavMoveFlags = ImGuiNavMoveFlags_None;
15970 g.NavMoveScrollFlags = ImGuiScrollFlags_None;
15971 if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
15973 const ImGuiInputFlags repeat_mode =
15974 ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateNavMove;
15975 if (!IsActiveIdUsingNavDir(ImGuiDir_Left) &&
15976 ((nav_gamepad_active &&
IsKeyPressed(ImGuiKey_GamepadDpadLeft, repeat_mode, ImGuiKeyOwner_NoOwner)) ||
15977 (nav_keyboard_active &&
IsKeyPressed(ImGuiKey_LeftArrow, repeat_mode, ImGuiKeyOwner_NoOwner))))
15979 g.NavMoveDir = ImGuiDir_Left;
15981 if (!IsActiveIdUsingNavDir(ImGuiDir_Right) &&
15982 ((nav_gamepad_active &&
IsKeyPressed(ImGuiKey_GamepadDpadRight, repeat_mode, ImGuiKeyOwner_NoOwner)) ||
15983 (nav_keyboard_active &&
IsKeyPressed(ImGuiKey_RightArrow, repeat_mode, ImGuiKeyOwner_NoOwner))))
15985 g.NavMoveDir = ImGuiDir_Right;
15987 if (!IsActiveIdUsingNavDir(ImGuiDir_Up) &&
15988 ((nav_gamepad_active &&
IsKeyPressed(ImGuiKey_GamepadDpadUp, repeat_mode, ImGuiKeyOwner_NoOwner)) ||
15989 (nav_keyboard_active &&
IsKeyPressed(ImGuiKey_UpArrow, repeat_mode, ImGuiKeyOwner_NoOwner))))
15991 g.NavMoveDir = ImGuiDir_Up;
15993 if (!IsActiveIdUsingNavDir(ImGuiDir_Down) &&
15994 ((nav_gamepad_active &&
IsKeyPressed(ImGuiKey_GamepadDpadDown, repeat_mode, ImGuiKeyOwner_NoOwner)) ||
15995 (nav_keyboard_active &&
IsKeyPressed(ImGuiKey_DownArrow, repeat_mode, ImGuiKeyOwner_NoOwner))))
15997 g.NavMoveDir = ImGuiDir_Down;
16000 g.NavMoveClipDir = g.NavMoveDir;
16001 g.NavScoringNoClipRect =
ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
16006 float scoring_rect_offset_y = 0.0f;
16007 if (window && g.NavMoveDir == ImGuiDir_None && nav_keyboard_active)
16008 scoring_rect_offset_y = NavUpdatePageUpPageDown();
16009 if (scoring_rect_offset_y != 0.0f)
16011 g.NavScoringNoClipRect = window->InnerRect;
16012 g.NavScoringNoClipRect.TranslateY(scoring_rect_offset_y);
16016#if IMGUI_DEBUG_NAV_SCORING
16021 if (g.NavMoveDir == ImGuiDir_None)
16022 g.NavMoveDir = g.NavMoveDirForDebug;
16023 g.NavMoveClipDir = g.NavMoveDir;
16024 g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult;
16029 g.NavMoveForwardToNextFrame =
false;
16030 if (g.NavMoveDir != ImGuiDir_None)
16031 NavMoveRequestSubmit(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags);
16035 if (g.NavMoveSubmitted && g.NavId == 0)
16037 IMGUI_DEBUG_LOG_NAV(
"[nav] NavInitRequest: from move, window \"%s\", layer=%d\n",
16038 window ? window->Name :
"<NULL>", g.NavLayer);
16039 g.NavInitRequest = g.NavInitRequestFromMove =
true;
16040 g.NavInitResult.ID = 0;
16041 if (g.IO.ConfigNavCursorVisibleAuto)
16042 g.NavCursorVisible =
true;
16048 if (g.NavMoveSubmitted && g.NavInputSource == ImGuiInputSource_Gamepad && g.NavLayer == ImGuiNavLayer_Main &&
16051 bool clamp_x = (g.NavMoveFlags & (ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapX)) == 0;
16052 bool clamp_y = (g.NavMoveFlags & (ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapY)) == 0;
16053 ImRect inner_rect_rel = WindowRectAbsToRel(
16054 window,
ImRect(window->InnerRect.Min -
ImVec2(1, 1), window->InnerRect.Max +
ImVec2(1, 1)));
16058 inner_rect_rel.Translate(CalcNextScrollFromScrollTargetAndClamp(window) - window->Scroll);
16060 if ((clamp_x || clamp_y) && !inner_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
16062 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequest: clamp NavRectRel for gamepad move\n");
16063 float pad_x = ImMin(inner_rect_rel.GetWidth(), window->FontRefSize * 0.5f);
16064 float pad_y = ImMin(
16065 inner_rect_rel.GetHeight(),
16066 window->FontRefSize *
16068 inner_rect_rel.Min.x = clamp_x ? (inner_rect_rel.Min.x + pad_x) : -FLT_MAX;
16069 inner_rect_rel.Max.x = clamp_x ? (inner_rect_rel.Max.x - pad_x) : +FLT_MAX;
16070 inner_rect_rel.Min.y = clamp_y ? (inner_rect_rel.Min.y + pad_y) : -FLT_MAX;
16071 inner_rect_rel.Max.y = clamp_y ? (inner_rect_rel.Max.y - pad_y) : +FLT_MAX;
16072 window->NavRectRel[g.NavLayer].ClipWithFull(inner_rect_rel);
16080 if (window != NULL)
16083 !window->NavRectRel[g.NavLayer].IsInverted() ? window->NavRectRel[g.NavLayer] :
ImRect(0, 0, 0, 0);
16084 scoring_rect = WindowRectRelToAbs(window, nav_rect_rel);
16085 scoring_rect.TranslateY(scoring_rect_offset_y);
16086 if (g.NavMoveSubmitted)
16087 NavBiasScoringRect(scoring_rect, window->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer],
16088 g.NavMoveDir, g.NavMoveFlags);
16089 IM_ASSERT(!scoring_rect.IsInverted());
16095 g.NavScoringRect = scoring_rect;
16096 g.NavScoringNoClipRect.Add(scoring_rect);
16099void ImGui::NavUpdateCreateTabbingRequest()
16103 IM_ASSERT(g.NavMoveDir == ImGuiDir_None);
16104 if (window == NULL || g.NavWindowingTarget != NULL || (window->Flags & ImGuiWindowFlags_NoNavInputs))
16107 const bool tab_pressed =
16108 IsKeyPressed(ImGuiKey_Tab, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner) && !g.IO.KeyCtrl && !g.IO.KeyAlt;
16116 const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
16117 if (nav_keyboard_active)
16118 g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.NavCursorVisible ==
false && g.ActiveId == 0) ? 0 : +1;
16120 g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.ActiveId == 0) ? 0 : +1;
16121 ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate;
16122 ImGuiScrollFlags scroll_flags = window->Appearing
16123 ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY
16124 : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
16125 ImGuiDir clip_dir = (g.NavTabbingDir < 0) ? ImGuiDir_Up : ImGuiDir_Down;
16126 NavMoveRequestSubmit(
16127 ImGuiDir_None, clip_dir, move_flags,
16129 g.NavTabbingCounter = -1;
16133void ImGui::NavMoveRequestApplyResult()
16136#if IMGUI_DEBUG_NAV_SCORING
16137 if (g.NavMoveFlags & ImGuiNavMoveFlags_DebugNoResult)
16142 ImGuiNavItemData *result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal
16143 : (g.NavMoveResultOther.ID != 0) ? &g.NavMoveResultOther
16147 if ((g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && result == NULL)
16148 if ((g.NavTabbingCounter == 1 || g.NavTabbingDir == 0) && g.NavTabbingResultFirst.ID)
16149 result = &g.NavTabbingResultFirst;
16153 const ImGuiAxis axis = (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X;
16154 if (result == NULL)
16156 if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
16157 g.NavMoveFlags |= ImGuiNavMoveFlags_NoSetNavCursorVisible;
16158 if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavCursorVisible) == 0)
16159 SetNavCursorVisibleAfterMove();
16160 NavClearPreferredPosForAxis(axis);
16161 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveSubmitted but not led to a result!\n");
16167 if (g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
16168 if (g.NavMoveResultLocalVisible.ID != 0 && g.NavMoveResultLocalVisible.ID != g.NavId)
16169 result = &g.NavMoveResultLocalVisible;
16172 if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 &&
16173 g.NavMoveResultOther.Window->ParentWindow == g.NavWindow)
16174 if ((g.NavMoveResultOther.DistBox < result->DistBox) ||
16175 (g.NavMoveResultOther.DistBox == result->DistBox && g.NavMoveResultOther.DistCenter < result->DistCenter))
16176 result = &g.NavMoveResultOther;
16177 IM_ASSERT(g.NavWindow && result->Window);
16180 if (g.NavLayer == ImGuiNavLayer_Main)
16182 ImRect rect_abs = WindowRectRelToAbs(result->Window, result->RectRel);
16183 ScrollToRectEx(result->Window, rect_abs, g.NavMoveScrollFlags);
16185 if (g.NavMoveFlags & ImGuiNavMoveFlags_ScrollToEdgeY)
16188 float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
16189 SetScrollY(result->Window, scroll_target);
16193 if (g.NavWindow != result->Window)
16195 IMGUI_DEBUG_LOG_FOCUS(
"[focus] NavMoveRequest: SetNavWindow(\"%s\")\n", result->Window->Name);
16196 g.NavWindow = result->Window;
16197 g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
16203 if (g.ActiveId != result->ID && (g.NavMoveFlags & ImGuiNavMoveFlags_NoClearActiveId) == 0)
16209 if ((g.NavId != result->ID || (g.NavMoveFlags & ImGuiNavMoveFlags_IsPageMove)) &&
16210 (g.NavMoveFlags & ImGuiNavMoveFlags_NoSelect) == 0)
16212 g.NavJustMovedFromFocusScopeId = g.NavFocusScopeId;
16213 g.NavJustMovedToId = result->ID;
16214 g.NavJustMovedToFocusScopeId = result->FocusScopeId;
16215 g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
16216 g.NavJustMovedToIsTabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0;
16217 g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
16223 IMGUI_DEBUG_LOG_NAV(
"[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer,
16224 g.NavWindow->Name);
16225 ImVec2 preferred_scoring_pos_rel = g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer];
16226 SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
16227 if (result->SelectionUserData != ImGuiSelectionUserData_Invalid)
16228 g.NavLastValidSelectionUserData = result->SelectionUserData;
16233 if ((g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) == 0)
16235 preferred_scoring_pos_rel[axis] = result->RectRel.GetCenter()[axis];
16236 g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer] = preferred_scoring_pos_rel;
16240 if ((g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && (result->ItemFlags & ImGuiItemFlags_Inputable) == 0)
16241 g.NavMoveFlags &= ~ImGuiNavMoveFlags_Activate;
16244 if (g.NavMoveFlags & ImGuiNavMoveFlags_Activate)
16246 g.NavNextActivateId = result->ID;
16247 g.NavNextActivateFlags = ImGuiActivateFlags_None;
16248 if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
16249 g.NavNextActivateFlags |=
16250 ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing;
16254 if ((g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavCursorVisible) == 0)
16255 SetNavCursorVisibleAfterMove();
16263static void ImGui::NavUpdateCancelRequest()
16266 const bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 &&
16267 (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
16268 const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
16269 if (!(nav_keyboard_active &&
IsKeyPressed(ImGuiKey_Escape, 0, ImGuiKeyOwner_NoOwner)) &&
16270 !(nav_gamepad_active &&
IsKeyPressed(ImGuiKey_NavGamepadCancel, 0, ImGuiKeyOwner_NoOwner)))
16273 IMGUI_DEBUG_LOG_NAV(
"[nav] NavUpdateCancelRequest()\n");
16274 if (g.ActiveId != 0)
16278 else if (g.NavLayer != ImGuiNavLayer_Main)
16281 NavRestoreLayer(ImGuiNavLayer_Main);
16282 SetNavCursorVisibleAfterMove();
16284 else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow &&
16285 !(g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) &&
16286 g.NavWindow->RootWindowForNav->ParentWindow)
16289 ImGuiWindow *child_window = g.NavWindow->RootWindowForNav;
16290 ImGuiWindow *parent_window = child_window->ParentWindow;
16291 IM_ASSERT(child_window->ChildId != 0);
16292 FocusWindow(parent_window);
16293 SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_window->Rect()));
16294 SetNavCursorVisibleAfterMove();
16296 else if (g.OpenPopupStack.Size > 0 && g.OpenPopupStack.back().Window != NULL &&
16297 !(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
16300 ClosePopupToLevel(g.OpenPopupStack.Size - 1,
true);
16307 if (g.IO.ConfigNavEscapeClearFocusItem || g.IO.ConfigNavEscapeClearFocusWindow)
16308 if (g.NavWindow && ((g.NavWindow->Flags &
16309 ImGuiWindowFlags_Popup)))
16310 g.NavWindow->NavLastIds[0] = 0;
16313 if (g.IO.ConfigNavEscapeClearFocusItem || g.IO.ConfigNavEscapeClearFocusWindow)
16315 if (g.IO.ConfigNavEscapeClearFocusWindow)
16324static float ImGui::NavUpdatePageUpPageDown()
16328 if ((window->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL)
16331 const bool page_up_held =
IsKeyDown(ImGuiKey_PageUp, ImGuiKeyOwner_NoOwner);
16332 const bool page_down_held =
IsKeyDown(ImGuiKey_PageDown, ImGuiKeyOwner_NoOwner);
16333 const bool home_pressed =
IsKeyPressed(ImGuiKey_Home, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner);
16334 const bool end_pressed =
IsKeyPressed(ImGuiKey_End, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner);
16335 if (page_up_held == page_down_held &&
16336 home_pressed == end_pressed)
16339 if (g.NavLayer != ImGuiNavLayer_Main)
16340 NavRestoreLayer(ImGuiNavLayer_Main);
16342 if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY)
16345 if (
IsKeyPressed(ImGuiKey_PageUp, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner))
16346 SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
16347 else if (
IsKeyPressed(ImGuiKey_PageDown, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner))
16348 SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
16349 else if (home_pressed)
16350 SetScrollY(window, 0.0f);
16351 else if (end_pressed)
16352 SetScrollY(window, window->ScrollMax.y);
16356 ImRect &nav_rect_rel = window->NavRectRel[g.NavLayer];
16357 const float page_offset_y =
16358 ImMax(0.0f, window->InnerRect.GetHeight() - window->FontRefSize * 1.0f + nav_rect_rel.GetHeight());
16359 float nav_scoring_rect_offset_y = 0.0f;
16362 nav_scoring_rect_offset_y = -page_offset_y;
16363 g.NavMoveDir = ImGuiDir_Down;
16365 g.NavMoveClipDir = ImGuiDir_Up;
16366 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet |
16367 ImGuiNavMoveFlags_IsPageMove;
16371 nav_scoring_rect_offset_y = +page_offset_y;
16372 g.NavMoveDir = ImGuiDir_Up;
16374 g.NavMoveClipDir = ImGuiDir_Down;
16375 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet |
16376 ImGuiNavMoveFlags_IsPageMove;
16378 else if (home_pressed)
16384 nav_rect_rel.Min.y = nav_rect_rel.Max.y = 0.0f;
16385 if (nav_rect_rel.IsInverted())
16386 nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
16387 g.NavMoveDir = ImGuiDir_Down;
16388 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
16391 else if (end_pressed)
16393 nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ContentSize.y;
16394 if (nav_rect_rel.IsInverted())
16395 nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
16396 g.NavMoveDir = ImGuiDir_Up;
16397 g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
16400 return nav_scoring_rect_offset_y;
16405static void ImGui::NavEndFrame()
16410 if (g.NavWindowingTarget != NULL)
16411 NavUpdateWindowingOverlay();
16418 if (g.NavWindow && NavMoveRequestButNoResultYet() && (g.NavMoveFlags & ImGuiNavMoveFlags_WrapMask_) &&
16419 (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
16420 NavUpdateCreateWrappingRequest();
16423static void ImGui::NavUpdateCreateWrappingRequest()
16428 bool do_forward =
false;
16429 ImRect bb_rel = window->NavRectRel[g.NavLayer];
16430 ImGuiDir clip_dir = g.NavMoveDir;
16432 const ImGuiNavMoveFlags move_flags = g.NavMoveFlags;
16435 if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
16437 bb_rel.Min.x = bb_rel.Max.x = window->ContentSize.x + window->WindowPadding.x;
16438 if (move_flags & ImGuiNavMoveFlags_WrapX)
16440 bb_rel.TranslateY(-bb_rel.GetHeight());
16441 clip_dir = ImGuiDir_Up;
16445 if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
16447 bb_rel.Min.x = bb_rel.Max.x = -window->WindowPadding.x;
16448 if (move_flags & ImGuiNavMoveFlags_WrapX)
16450 bb_rel.TranslateY(+bb_rel.GetHeight());
16451 clip_dir = ImGuiDir_Down;
16455 if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
16457 bb_rel.Min.y = bb_rel.Max.y = window->ContentSize.y + window->WindowPadding.y;
16458 if (move_flags & ImGuiNavMoveFlags_WrapY)
16460 bb_rel.TranslateX(-bb_rel.GetWidth());
16461 clip_dir = ImGuiDir_Left;
16465 if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
16467 bb_rel.Min.y = bb_rel.Max.y = -window->WindowPadding.y;
16468 if (move_flags & ImGuiNavMoveFlags_WrapY)
16470 bb_rel.TranslateX(+bb_rel.GetWidth());
16471 clip_dir = ImGuiDir_Right;
16477 window->NavRectRel[g.NavLayer] = bb_rel;
16478 NavClearPreferredPosForAxis(ImGuiAxis_X);
16479 NavClearPreferredPosForAxis(ImGuiAxis_Y);
16480 NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags);
16486bool ImGui::IsWindowNavFocusable(
ImGuiWindow *window)
16488 return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
16491static ImGuiWindow *FindWindowNavFocusable(
int i_start,
int i_stop,
int dir)
16494 for (
int i = i_start; i >= 0 && i < g.WindowsFocusOrder.Size && i != i_stop; i += dir)
16495 if (ImGui::IsWindowNavFocusable(g.WindowsFocusOrder[i]))
16496 return g.WindowsFocusOrder[i];
16500static void NavUpdateWindowingTarget(
int focus_change_dir)
16503 IM_ASSERT(g.NavWindowingTarget);
16504 if (g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)
16507 const int i_current = ImGui::FindWindowFocusIndex(g.NavWindowingTarget);
16508 ImGuiWindow *window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir);
16509 if (!window_target)
16510 window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (g.WindowsFocusOrder.Size - 1) : 0, i_current,
16514 g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target;
16515 g.NavWindowingAccumDeltaPos = g.NavWindowingAccumDeltaSize =
ImVec2(0.0f, 0.0f);
16517 g.NavWindowingToggleLayer =
false;
16521static void ImGui::NavUpdateWindowingApplyFocus(
ImGuiWindow *apply_focus_window)
16527 if (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow)
16529 ImGuiViewport *previous_viewport = g.NavWindow ? g.NavWindow->Viewport : NULL;
16531 SetNavCursorVisibleAfterMove();
16532 ClosePopupsOverWindow(apply_focus_window,
false);
16533 FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild);
16534 apply_focus_window = g.NavWindow;
16535 if (apply_focus_window->NavLastIds[0] == 0)
16536 NavInitWindow(apply_focus_window,
false);
16545 if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu))
16546 g.NavLayer = ImGuiNavLayer_Menu;
16549 if (apply_focus_window->Viewport != previous_viewport && g.PlatformIO.Platform_SetWindowFocus)
16550 g.PlatformIO.Platform_SetWindowFocus(apply_focus_window->Viewport);
16552 g.NavWindowingTarget = NULL;
16558static void ImGui::NavUpdateWindowing()
16564 bool apply_toggle_layer =
false;
16566 ImGuiWindow *modal_window = GetTopMostPopupModal();
16567 bool allow_windowing = (modal_window == NULL);
16569 if (!allow_windowing)
16570 g.NavWindowingTarget = NULL;
16573 if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL)
16575 g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - io.DeltaTime * 10.0f, 0.0f);
16576 if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f)
16577 g.NavWindowingTargetAnim = NULL;
16583 const ImGuiID owner_id = ImHashStr(
"##NavUpdateWindowing");
16584 const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 &&
16585 (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
16586 const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
16587 const bool keyboard_next_window =
16588 allow_windowing && g.ConfigNavWindowingKeyNext &&
16589 Shortcut(g.ConfigNavWindowingKeyNext, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways, owner_id);
16590 const bool keyboard_prev_window =
16591 allow_windowing && g.ConfigNavWindowingKeyPrev &&
16592 Shortcut(g.ConfigNavWindowingKeyPrev, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways, owner_id);
16593 const bool start_windowing_with_gamepad = allow_windowing && nav_gamepad_active && !g.NavWindowingTarget &&
16594 Shortcut(ImGuiKey_NavGamepadMenu, ImGuiInputFlags_RouteAlways, owner_id);
16595 const bool start_windowing_with_keyboard =
16596 allow_windowing && !g.NavWindowingTarget &&
16597 (keyboard_next_window || keyboard_prev_window);
16598 bool just_started_windowing_from_null_focus =
false;
16599 if (start_windowing_with_gamepad || start_windowing_with_keyboard)
16601 g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
16603 if (start_windowing_with_keyboard || g.ConfigNavWindowingWithGamepad)
16604 g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow;
16605 g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;
16606 g.NavWindowingAccumDeltaPos = g.NavWindowingAccumDeltaSize =
ImVec2(0.0f, 0.0f);
16607 g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true :
false;
16608 g.NavWindowingInputSource = g.NavInputSource =
16609 start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
16610 if (g.NavWindow == NULL)
16611 just_started_windowing_from_null_focus =
true;
16615 if (keyboard_next_window || keyboard_prev_window)
16616 SetKeyOwnersForKeyChord((g.ConfigNavWindowingKeyNext | g.ConfigNavWindowingKeyPrev) & ImGuiMod_Mask_,
16621 if ((g.NavWindowingTarget || g.NavWindowingToggleLayer) && g.NavWindowingInputSource == ImGuiInputSource_Gamepad)
16623 if (g.NavWindowingTarget != NULL)
16628 g.NavWindowingTimer += io.DeltaTime;
16629 g.NavWindowingHighlightAlpha =
16630 ImMax(g.NavWindowingHighlightAlpha,
16631 ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
16635 if (focus_change_dir != 0 && !just_started_windowing_from_null_focus)
16637 NavUpdateWindowingTarget(focus_change_dir);
16638 g.NavWindowingHighlightAlpha = 1.0f;
16644 if (!
IsKeyDown(ImGuiKey_NavGamepadMenu))
16646 g.NavWindowingToggleLayer &=
16647 (g.NavWindowingHighlightAlpha <
16649 if (g.NavWindowingToggleLayer && g.NavWindow)
16650 apply_toggle_layer =
true;
16651 else if (!g.NavWindowingToggleLayer)
16652 apply_focus_window = g.NavWindowingTarget;
16653 g.NavWindowingTarget = NULL;
16654 g.NavWindowingToggleLayer =
false;
16659 if (g.NavWindowingTarget && g.NavWindowingInputSource == ImGuiInputSource_Keyboard)
16663 ImGuiKeyChord shared_mods = ((g.ConfigNavWindowingKeyNext ? g.ConfigNavWindowingKeyNext : ImGuiMod_Mask_) &
16664 (g.ConfigNavWindowingKeyPrev ? g.ConfigNavWindowingKeyPrev : ImGuiMod_Mask_)) &
16666 IM_ASSERT(shared_mods != 0);
16668 g.NavWindowingTimer += io.DeltaTime;
16669 g.NavWindowingHighlightAlpha =
16670 ImMax(g.NavWindowingHighlightAlpha,
16671 ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
16672 if ((keyboard_next_window || keyboard_prev_window) && !just_started_windowing_from_null_focus)
16673 NavUpdateWindowingTarget(keyboard_next_window ? -1 : +1);
16674 else if ((io.KeyMods & shared_mods) != shared_mods)
16675 apply_focus_window = g.NavWindowingTarget;
16679 const ImGuiKey windowing_toggle_keys[] = {ImGuiKey_LeftAlt, ImGuiKey_RightAlt};
16680 bool windowing_toggle_layer_start =
false;
16681 if (g.NavWindow != NULL && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
16682 for (ImGuiKey windowing_toggle_key : windowing_toggle_keys)
16683 if (nav_keyboard_active &&
IsKeyPressed(windowing_toggle_key, 0, ImGuiKeyOwner_NoOwner))
16685 windowing_toggle_layer_start =
true;
16686 g.NavWindowingToggleLayer =
true;
16687 g.NavWindowingToggleKey = windowing_toggle_key;
16688 g.NavWindowingInputSource = g.NavInputSource = ImGuiInputSource_Keyboard;
16691 if (g.NavWindowingToggleLayer && g.NavWindowingInputSource == ImGuiInputSource_Keyboard)
16697 if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper)
16698 g.NavWindowingToggleLayer =
false;
16699 else if (windowing_toggle_layer_start ==
false && g.LastKeyboardKeyPressTime == g.Time)
16700 g.NavWindowingToggleLayer =
false;
16701 else if (TestKeyOwner(g.NavWindowingToggleKey, ImGuiKeyOwner_NoOwner) ==
false ||
16702 TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_NoOwner) ==
false)
16703 g.NavWindowingToggleLayer =
false;
16708 if (
IsKeyReleased(g.NavWindowingToggleKey) && g.NavWindowingToggleLayer)
16709 if (g.ActiveId == 0 || g.ActiveIdAllowOverlap)
16710 if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev))
16711 apply_toggle_layer =
true;
16712 if (!
IsKeyDown(g.NavWindowingToggleKey))
16713 g.NavWindowingToggleLayer =
false;
16717 if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
16720 if (g.NavInputSource == ImGuiInputSource_Keyboard && !io.KeyShift)
16722 GetKeyMagnitude2d(ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow);
16723 if (g.NavInputSource == ImGuiInputSource_Gamepad)
16724 nav_move_dir = GetKeyMagnitude2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight,
16725 ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown);
16726 if (nav_move_dir.x != 0.0f || nav_move_dir.y != 0.0f)
16728 const float NAV_MOVE_SPEED = 800.0f;
16729 const float move_step =
16730 NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
16731 g.NavWindowingAccumDeltaPos += nav_move_dir * move_step;
16732 g.NavHighlightItemUnderNav =
true;
16733 ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaPos);
16734 if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
16736 ImGuiWindow *moving_window = g.NavWindowingTarget->RootWindowDockTree;
16737 SetWindowPos(moving_window, moving_window->Pos + accum_floored, ImGuiCond_Always);
16738 g.NavWindowingAccumDeltaPos -= accum_floored;
16744 if (apply_focus_window)
16745 NavUpdateWindowingApplyFocus(apply_focus_window);
16748 if (apply_toggle_layer && g.NavWindow)
16754 while (new_nav_window->ParentWindow &&
16755 (new_nav_window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0 &&
16756 (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 &&
16757 (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
16758 new_nav_window = new_nav_window->ParentWindow;
16759 if (new_nav_window != g.NavWindow)
16762 FocusWindow(new_nav_window);
16763 new_nav_window->NavLastChildNavWindow = old_nav_window;
16767 const ImGuiNavLayer new_nav_layer = (g.NavWindow->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu))
16768 ? (ImGuiNavLayer)((
int)g.NavLayer ^ 1)
16769 : ImGuiNavLayer_Main;
16770 if (new_nav_layer != g.NavLayer)
16774 const bool preserve_layer_1_nav_id = (new_nav_window->DockNodeAsHost != NULL);
16775 if (new_nav_layer == ImGuiNavLayer_Menu && !preserve_layer_1_nav_id)
16776 g.NavWindow->NavLastIds[new_nav_layer] = 0;
16777 NavRestoreLayer(new_nav_layer);
16778 SetNavCursorVisibleAfterMove();
16784static const char *GetFallbackWindowNameForWindowingList(
ImGuiWindow *window)
16786 if (window->Flags & ImGuiWindowFlags_Popup)
16787 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingPopup);
16788 if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name,
"##MainMenuBar") == 0)
16789 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingMainMenuBar);
16790 if (window->DockNodeAsHost)
16791 return "(Dock node)";
16792 return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingUntitled);
16796void ImGui::NavUpdateWindowingOverlay()
16799 IM_ASSERT(g.NavWindowingTarget != NULL);
16801 if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY)
16804 if (g.NavWindowingListWindow == NULL)
16805 g.NavWindowingListWindow = FindWindowByName(
"##NavWindowingOverlay");
16807 SetNextWindowSizeConstraints(
ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f),
ImVec2(FLT_MAX, FLT_MAX));
16808 SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Always,
ImVec2(0.5f, 0.5f));
16809 PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f);
16810 Begin(
"##NavWindowingOverlay", NULL,
16811 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize |
16812 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize |
16813 ImGuiWindowFlags_NoSavedSettings);
16814 if (g.ContextName[0] != 0)
16815 SeparatorText(g.ContextName);
16816 for (
int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--)
16819 IM_ASSERT(window != NULL);
16820 if (!IsWindowNavFocusable(window))
16822 const char *label = window->Name;
16823 if (label == FindRenderedTextEnd(label))
16824 label = GetFallbackWindowNameForWindowingList(window);
16825 Selectable(label, g.NavWindowingTarget == window);
16835bool ImGui::IsDragDropActive()
16838 return g.DragDropActive;
16841void ImGui::ClearDragDrop()
16844 if (g.DragDropActive)
16845 IMGUI_DEBUG_LOG_ACTIVEID(
"[dragdrop] ClearDragDrop()\n");
16846 g.DragDropActive =
false;
16847 g.DragDropPayload.Clear();
16848 g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
16849 g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0;
16850 g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
16851 g.DragDropAcceptFrameCount = -1;
16853 g.DragDropPayloadBufHeap.clear();
16854 memset(&g.DragDropPayloadBufLocal, 0,
sizeof(g.DragDropPayloadBufLocal));
16857bool ImGui::BeginTooltipHidden()
16860 bool ret = Begin(
"##Tooltip_Hidden", NULL,
16861 ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar |
16862 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings |
16863 ImGuiWindowFlags_AlwaysAutoResize);
16864 SetWindowHiddenAndSkipItemsForCurrentFrame(g.CurrentWindow);
16876bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
16883 ImGuiMouseButton mouse_button = ImGuiMouseButton_Left;
16885 bool source_drag_active =
false;
16886 ImGuiID source_id = 0;
16887 ImGuiID source_parent_id = 0;
16888 if ((flags & ImGuiDragDropFlags_SourceExtern) == 0)
16890 source_id = g.LastItemData.ID;
16891 if (source_id != 0)
16894 if (g.ActiveId != source_id)
16896 if (g.ActiveIdMouseButton != -1)
16897 mouse_button = g.ActiveIdMouseButton;
16898 if (g.IO.MouseDown[mouse_button] ==
false || window->SkipItems)
16900 g.ActiveIdAllowOverlap =
false;
16905 if (g.IO.MouseDown[mouse_button] ==
false || window->SkipItems)
16907 if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 &&
16908 (g.ActiveId == 0 || g.ActiveIdWindow != window))
16914 if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
16926 source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect);
16927 KeepAliveID(source_id);
16928 bool is_hovered = ItemHoverable(g.LastItemData.Rect, source_id, g.LastItemData.ItemFlags);
16929 if (is_hovered && g.IO.MouseClicked[mouse_button])
16931 SetActiveID(source_id, window);
16932 FocusWindow(window);
16934 if (g.ActiveId == source_id)
16936 g.ActiveIdAllowOverlap = is_hovered;
16938 if (g.ActiveId != source_id)
16940 source_parent_id = window->IDStack.back();
16941 source_drag_active = IsMouseDragging(mouse_button);
16944 SetActiveIdUsingAllKeyboardKeys();
16950 source_id = ImHashStr(
"#SourceExtern");
16951 source_drag_active =
true;
16952 mouse_button = g.IO.MouseDown[0] ? 0 : -1;
16953 KeepAliveID(source_id);
16954 SetActiveID(source_id, NULL);
16957 IM_ASSERT(g.DragDropWithinTarget ==
false);
16958 if (!source_drag_active)
16962 if (!g.DragDropActive)
16964 IM_ASSERT(source_id != 0);
16966 IMGUI_DEBUG_LOG_ACTIVEID(
"[dragdrop] BeginDragDropSource() DragDropActive = true, source_id = 0x%08X%s\n",
16967 source_id, (flags & ImGuiDragDropFlags_SourceExtern) ?
" (EXTERN)" :
"");
16969 payload.SourceId = source_id;
16970 payload.SourceParentId = source_parent_id;
16971 g.DragDropActive =
true;
16972 g.DragDropSourceFlags = flags;
16973 g.DragDropMouseButton = mouse_button;
16974 if (payload.SourceId == g.ActiveId)
16975 g.ActiveIdNoClearOnFocusLoss =
true;
16977 g.DragDropSourceFrameCount = g.FrameCount;
16978 g.DragDropWithinSource =
true;
16980 if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
16986 if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
16987 ret = BeginTooltipHidden();
16989 ret = BeginTooltip();
16995 if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
16996 g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
17001void ImGui::EndDragDropSource()
17004 IM_ASSERT(g.DragDropActive);
17005 IM_ASSERT(g.DragDropWithinSource &&
"Not after a BeginDragDropSource()?");
17007 if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
17011 if (g.DragDropPayload.DataFrameCount == -1)
17013 g.DragDropWithinSource =
false;
17017bool ImGui::SetDragDropPayload(
const char *type,
const void *data,
size_t data_size, ImGuiCond cond)
17022 cond = ImGuiCond_Always;
17024 IM_ASSERT(type != NULL);
17025 IM_ASSERT(ImStrlen(type) < IM_ARRAYSIZE(payload.DataType) &&
"Payload type can be at most 32 characters long");
17026 IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
17027 IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
17028 IM_ASSERT(payload.SourceId != 0);
17030 if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
17033 ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
17034 g.DragDropPayloadBufHeap.resize(0);
17035 if (data_size >
sizeof(g.DragDropPayloadBufLocal))
17038 g.DragDropPayloadBufHeap.resize((
int)data_size);
17039 payload.Data = g.DragDropPayloadBufHeap.Data;
17040 memcpy(payload.Data, data, data_size);
17042 else if (data_size > 0)
17045 memset(&g.DragDropPayloadBufLocal, 0,
sizeof(g.DragDropPayloadBufLocal));
17046 payload.Data = g.DragDropPayloadBufLocal;
17047 memcpy(payload.Data, data, data_size);
17051 payload.Data = NULL;
17053 payload.DataSize = (int)data_size;
17055 payload.DataFrameCount = g.FrameCount;
17058 return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1);
17061bool ImGui::BeginDragDropTargetCustom(
const ImRect &bb, ImGuiID
id)
17064 if (!g.DragDropActive)
17068 ImGuiWindow *hovered_window = g.HoveredWindowUnderMovingWindow;
17069 if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree)
17071 IM_ASSERT(
id != 0);
17072 if (!IsMouseHoveringRect(bb.Min, bb.Max) || (
id == g.DragDropPayload.SourceId))
17074 if (window->SkipItems)
17077 IM_ASSERT(g.DragDropWithinTarget ==
false &&
17078 g.DragDropWithinSource ==
false);
17079 g.DragDropTargetRect = bb;
17080 g.DragDropTargetClipRect = window->ClipRect;
17081 g.DragDropTargetId = id;
17082 g.DragDropWithinTarget =
true;
17091bool ImGui::BeginDragDropTarget()
17094 if (!g.DragDropActive)
17098 if (!(g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect))
17100 ImGuiWindow *hovered_window = g.HoveredWindowUnderMovingWindow;
17101 if (hovered_window == NULL || window->RootWindowDockTree != hovered_window->RootWindowDockTree || window->SkipItems)
17104 const ImRect &display_rect = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDisplayRect)
17105 ? g.LastItemData.DisplayRect
17106 : g.LastItemData.Rect;
17107 ImGuiID
id = g.LastItemData.ID;
17110 id = window->GetIDFromRectangle(display_rect);
17113 if (g.DragDropPayload.SourceId ==
id)
17116 IM_ASSERT(g.DragDropWithinTarget ==
false &&
17117 g.DragDropWithinSource ==
false);
17118 g.DragDropTargetRect = display_rect;
17119 g.DragDropTargetClipRect =
17120 (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasClipRect) ? g.LastItemData.ClipRect : window->ClipRect;
17121 g.DragDropTargetId = id;
17122 g.DragDropWithinTarget =
true;
17126bool ImGui::IsDragDropPayloadBeingAccepted()
17129 return g.DragDropActive && g.DragDropAcceptIdPrev != 0;
17132const ImGuiPayload *ImGui::AcceptDragDropPayload(
const char *type, ImGuiDragDropFlags flags)
17136 IM_ASSERT(g.DragDropActive);
17137 IM_ASSERT(payload.DataFrameCount != -1);
17138 if (type != NULL && !payload.IsDataType(type))
17144 const bool was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId);
17145 ImRect r = g.DragDropTargetRect;
17146 float r_surface = r.GetWidth() * r.GetHeight();
17147 if (r_surface > g.DragDropAcceptIdCurrRectSurface)
17150 g.DragDropAcceptFlags = flags;
17151 g.DragDropAcceptIdCurr = g.DragDropTargetId;
17152 g.DragDropAcceptIdCurrRectSurface = r_surface;
17156 payload.Preview = was_accepted_previously;
17157 flags |= (g.DragDropSourceFlags &
17158 ImGuiDragDropFlags_AcceptNoDrawDefaultRect);
17160 if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
17161 RenderDragDropTargetRect(r, g.DragDropTargetClipRect);
17163 g.DragDropAcceptFrameCount = g.FrameCount;
17164 if ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) && g.DragDropMouseButton == -1)
17165 payload.Delivery = was_accepted_previously && (g.DragDropSourceFrameCount < g.FrameCount);
17168 was_accepted_previously &&
17169 !IsMouseDown(g.DragDropMouseButton);
17171 if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery))
17174 if (payload.Delivery)
17175 IMGUI_DEBUG_LOG_ACTIVEID(
"[dragdrop] AcceptDragDropPayload(): 0x%08X: payload delivery\n", g.DragDropTargetId);
17180void ImGui::RenderDragDropTargetRect(
const ImRect &bb,
const ImRect &item_clip_rect)
17185 bb_display.ClipWith(
17187 bb_display.Expand(3.5f);
17188 bool push_clip_rect = !window->ClipRect.Contains(bb_display);
17189 if (push_clip_rect)
17190 window->DrawList->PushClipRectFullScreen();
17191 window->DrawList->AddRect(bb_display.Min, bb_display.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0,
17193 if (push_clip_rect)
17194 window->DrawList->PopClipRect();
17200 return (g.DragDropActive && g.DragDropPayload.DataFrameCount != -1) ? &g.DragDropPayload : NULL;
17203void ImGui::EndDragDropTarget()
17206 IM_ASSERT(g.DragDropActive);
17207 IM_ASSERT(g.DragDropWithinTarget);
17208 g.DragDropWithinTarget =
false;
17211 if (g.DragDropPayload.Delivery)
17223static inline void LogTextV(
ImGuiContext &g,
const char *fmt, va_list args)
17227 g.LogBuffer.Buf.resize(0);
17228 g.LogBuffer.appendfv(fmt, args);
17229 ImFileWrite(g.LogBuffer.c_str(),
sizeof(
char), (ImU64)g.LogBuffer.size(), g.LogFile);
17233 g.LogBuffer.appendfv(fmt, args);
17237void ImGui::LogText(
const char *fmt, ...)
17244 va_start(args, fmt);
17245 LogTextV(g, fmt, args);
17249void ImGui::LogTextV(
const char *fmt, va_list args)
17255 LogTextV(g, fmt, args);
17261void ImGui::LogRenderedText(
const ImVec2 *ref_pos,
const char *text,
const char *text_end)
17266 const char *prefix = g.LogNextPrefix;
17267 const char *suffix = g.LogNextSuffix;
17268 g.LogNextPrefix = g.LogNextSuffix = NULL;
17271 text_end = FindRenderedTextEnd(text, text_end);
17273 const bool log_new_line = ref_pos && (ref_pos->y > g.LogLinePosY + g.Style.FramePadding.y + 1);
17275 g.LogLinePosY = ref_pos->y;
17278 LogText(IM_NEWLINE);
17279 g.LogLineFirstItem =
true;
17283 LogRenderedText(ref_pos, prefix,
17284 prefix + ImStrlen(prefix));
17287 if (g.LogDepthRef > window->DC.TreeDepth)
17288 g.LogDepthRef = window->DC.TreeDepth;
17289 const int tree_depth = (window->DC.TreeDepth - g.LogDepthRef);
17291 const char *text_remaining = text;
17296 const char *line_start = text_remaining;
17297 const char *line_end = ImStreolRange(line_start, text_end);
17298 const bool is_last_line = (line_end == text_end);
17299 if (line_start != line_end || !is_last_line)
17301 const int line_length = (int)(line_end - line_start);
17302 const int indentation = g.LogLineFirstItem ? tree_depth * 4 : 1;
17303 LogText(
"%*s%.*s", indentation,
"", line_length, line_start);
17304 g.LogLineFirstItem =
false;
17305 if (*line_end ==
'\n')
17307 LogText(IM_NEWLINE);
17308 g.LogLineFirstItem =
true;
17313 text_remaining = line_end + 1;
17317 LogRenderedText(ref_pos, suffix, suffix + ImStrlen(suffix));
17321void ImGui::LogBegin(ImGuiLogFlags flags,
int auto_open_depth)
17325 IM_ASSERT(g.LogEnabled ==
false);
17326 IM_ASSERT(g.LogFile == NULL && g.LogBuffer.empty());
17327 IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiLogFlags_OutputMask_));
17329 g.LogEnabled = g.ItemUnclipByLog =
true;
17330 g.LogFlags = flags;
17331 g.LogWindow = window;
17332 g.LogNextPrefix = g.LogNextSuffix = NULL;
17333 g.LogDepthRef = window->DC.TreeDepth;
17334 g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth : g.LogDepthToExpandDefault);
17335 g.LogLinePosY = FLT_MAX;
17336 g.LogLineFirstItem =
true;
17341void ImGui::LogSetNextTextDecoration(
const char *prefix,
const char *suffix)
17344 g.LogNextPrefix = prefix;
17345 g.LogNextSuffix = suffix;
17348void ImGui::LogToTTY(
int auto_open_depth)
17353 IM_UNUSED(auto_open_depth);
17354#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
17355 LogBegin(ImGuiLogFlags_OutputTTY, auto_open_depth);
17356 g.LogFile = stdout;
17361void ImGui::LogToFile(
int auto_open_depth,
const char *filename)
17371 filename = g.IO.LogFilename;
17372 if (!filename || !filename[0])
17374 ImFileHandle f = ImFileOpen(filename,
"ab");
17381 LogBegin(ImGuiLogFlags_OutputFile, auto_open_depth);
17386void ImGui::LogToClipboard(
int auto_open_depth)
17391 LogBegin(ImGuiLogFlags_OutputClipboard, auto_open_depth);
17394void ImGui::LogToBuffer(
int auto_open_depth)
17399 LogBegin(ImGuiLogFlags_OutputBuffer, auto_open_depth);
17402void ImGui::LogFinish()
17408 LogText(IM_NEWLINE);
17409 switch (g.LogFlags & ImGuiLogFlags_OutputMask_)
17411 case ImGuiLogFlags_OutputTTY:
17412#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
17416 case ImGuiLogFlags_OutputFile:
17417 ImFileClose(g.LogFile);
17419 case ImGuiLogFlags_OutputBuffer:
17421 case ImGuiLogFlags_OutputClipboard:
17422 if (!g.LogBuffer.empty())
17423 SetClipboardText(g.LogBuffer.begin());
17430 g.LogEnabled = g.ItemUnclipByLog =
false;
17431 g.LogFlags = ImGuiLogFlags_None;
17433 g.LogBuffer.clear();
17439void ImGui::LogButtons()
17443 PushID(
"LogButtons");
17444#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
17445 const bool log_to_tty = Button(
"Log To TTY");
17448 const bool log_to_tty =
false;
17450 const bool log_to_file = Button(
"Log To File");
17452 const bool log_to_clipboard = Button(
"Log To Clipboard");
17454 PushItemFlag(ImGuiItemFlags_NoTabStop,
true);
17455 SetNextItemWidth(80.0f);
17456 SliderInt(
"Default Depth", &g.LogDepthToExpandDefault, 0, 9, NULL);
17465 if (log_to_clipboard)
17489void ImGui::UpdateSettings()
17493 if (!g.SettingsLoaded)
17495 IM_ASSERT(g.SettingsWindows.empty());
17496 if (g.IO.IniFilename)
17497 LoadIniSettingsFromDisk(g.IO.IniFilename);
17498 g.SettingsLoaded =
true;
17502 if (g.SettingsDirtyTimer > 0.0f)
17504 g.SettingsDirtyTimer -= g.IO.DeltaTime;
17505 if (g.SettingsDirtyTimer <= 0.0f)
17507 if (g.IO.IniFilename != NULL)
17508 SaveIniSettingsToDisk(g.IO.IniFilename);
17510 g.IO.WantSaveIniSettings =
true;
17512 g.SettingsDirtyTimer = 0.0f;
17517void ImGui::MarkIniSettingsDirty()
17520 if (g.SettingsDirtyTimer <= 0.0f)
17521 g.SettingsDirtyTimer = g.IO.IniSavingRate;
17524void ImGui::MarkIniSettingsDirty(
ImGuiWindow *window)
17527 if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
17528 if (g.SettingsDirtyTimer <= 0.0f)
17529 g.SettingsDirtyTimer = g.IO.IniSavingRate;
17535 IM_ASSERT(FindSettingsHandler(handler->TypeName) == NULL);
17536 g.SettingsHandlers.push_back(*handler);
17539void ImGui::RemoveSettingsHandler(
const char *type_name)
17543 g.SettingsHandlers.erase(handler);
17549 const ImGuiID type_hash = ImHashStr(type_name);
17551 if (handler.TypeHash == type_hash)
17557void ImGui::ClearIniSettings()
17560 g.SettingsIniData.clear();
17562 if (handler.ClearAllFn != NULL)
17563 handler.ClearAllFn(&g, &handler);
17566void ImGui::LoadIniSettingsFromDisk(
const char *ini_filename)
17568 size_t file_data_size = 0;
17569 char *file_data = (
char *)ImFileLoadToMemory(ini_filename,
"rb", &file_data_size);
17572 if (file_data_size > 0)
17573 LoadIniSettingsFromMemory(file_data, (
size_t)file_data_size);
17574 IM_FREE(file_data);
17579void ImGui::LoadIniSettingsFromMemory(
const char *ini_data,
size_t ini_size)
17582 IM_ASSERT(g.Initialized);
17590 ini_size = ImStrlen(ini_data);
17591 g.SettingsIniData.Buf.resize((
int)ini_size + 1);
17592 char *
const buf = g.SettingsIniData.Buf.Data;
17593 char *
const buf_end = buf + ini_size;
17594 memcpy(buf, ini_data, ini_size);
17600 if (handler.ReadInitFn != NULL)
17601 handler.ReadInitFn(&g, &handler);
17603 void *entry_data = NULL;
17606 char *line_end = NULL;
17607 for (
char *line = buf; line < buf_end; line = line_end + 1)
17610 while (*line ==
'\n' || *line ==
'\r')
17613 while (line_end < buf_end && *line_end !=
'\n' && *line_end !=
'\r')
17616 if (line[0] ==
';')
17618 if (line[0] ==
'[' && line_end > line && line_end[-1] ==
']')
17623 const char *name_end = line_end - 1;
17624 const char *type_start = line + 1;
17625 char *type_end = (
char *)(
void *)ImStrchrRange(type_start, name_end,
']');
17626 const char *name_start = type_end ? ImStrchrRange(type_end + 1, name_end,
'[') : NULL;
17627 if (!type_end || !name_start)
17631 entry_handler = FindSettingsHandler(type_start);
17632 entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL;
17634 else if (entry_handler != NULL && entry_data != NULL)
17637 entry_handler->ReadLineFn(&g, entry_handler, entry_data, line);
17640 g.SettingsLoaded =
true;
17643 memcpy(buf, ini_data, ini_size);
17647 if (handler.ApplyAllFn != NULL)
17648 handler.ApplyAllFn(&g, &handler);
17651void ImGui::SaveIniSettingsToDisk(
const char *ini_filename)
17654 g.SettingsDirtyTimer = 0.0f;
17658 size_t ini_data_size = 0;
17659 const char *ini_data = SaveIniSettingsToMemory(&ini_data_size);
17660 ImFileHandle f = ImFileOpen(ini_filename,
"wt");
17663 ImFileWrite(ini_data,
sizeof(
char), ini_data_size, f);
17669const char *ImGui::SaveIniSettingsToMemory(
size_t *out_size)
17672 g.SettingsDirtyTimer = 0.0f;
17673 g.SettingsIniData.Buf.resize(0);
17674 g.SettingsIniData.Buf.push_back(0);
17676 handler.WriteAllFn(&g, &handler, &g.SettingsIniData);
17678 *out_size = (size_t)g.SettingsIniData.size();
17679 return g.SettingsIniData.c_str();
17686 if (g.IO.ConfigDebugIniSettings ==
false)
17690 if (
const char *p = strstr(name,
"###"))
17693 const size_t name_len = ImStrlen(name);
17699 settings->ID = ImHashStr(name, name_len);
17700 memcpy(settings->GetName(), name, name_len + 1);
17711 settings = g.SettingsWindows.next_chunk(settings))
17712 if (settings->ID ==
id && !settings->WantDelete)
17721 if (window->SettingsOffset != -1)
17722 return g.SettingsWindows.ptr_from_offset(window->SettingsOffset);
17723 return FindWindowSettingsByID(window->ID);
17728void ImGui::ClearWindowSettings(
const char *name)
17733 if (window != NULL)
17735 window->Flags |= ImGuiWindowFlags_NoSavedSettings;
17736 InitOrLoadWindowSettings(window, NULL);
17737 if (window->DockId != 0)
17738 DockContextProcessUndockWindow(&g, window,
true);
17741 window ? FindWindowSettingsByWindow(window) : FindWindowSettingsByID(ImHashStr(name)))
17742 settings->WantDelete = true;
17749 window->SettingsOffset = -1;
17750 g.SettingsWindows.clear();
17755 ImGuiID
id = ImHashStr(name);
17760 settings = ImGui::CreateNewWindowSettings(name);
17762 settings->WantApply =
true;
17763 return (
void *)settings;
17772 if (sscanf(line,
"Pos=%i,%i", &x, &y) == 2)
17774 settings->Pos =
ImVec2ih((
short)x, (
short)y);
17776 else if (sscanf(line,
"Size=%i,%i", &x, &y) == 2)
17778 settings->Size =
ImVec2ih((
short)x, (
short)y);
17780 else if (sscanf(line,
"ViewportId=0x%08X", &u1) == 1)
17782 settings->ViewportId = u1;
17784 else if (sscanf(line,
"ViewportPos=%i,%i", &x, &y) == 2)
17786 settings->ViewportPos =
ImVec2ih((
short)x, (
short)y);
17788 else if (sscanf(line,
"Collapsed=%d", &i) == 1)
17790 settings->Collapsed = (i != 0);
17792 else if (sscanf(line,
"IsChild=%d", &i) == 1)
17794 settings->IsChild = (i != 0);
17796 else if (sscanf(line,
"DockId=0x%X,%d", &u1, &i) == 2)
17798 settings->DockId = u1;
17799 settings->DockOrder = (short)i;
17801 else if (sscanf(line,
"DockId=0x%X", &u1) == 1)
17803 settings->DockId = u1;
17804 settings->DockOrder = -1;
17806 else if (sscanf(line,
"ClassId=0x%X", &u1) == 1)
17808 settings->ClassId = u1;
17817 settings = g.SettingsWindows.next_chunk(settings))
17818 if (settings->WantApply)
17820 if (
ImGuiWindow *window = ImGui::FindWindowByID(settings->ID))
17821 ApplyWindowSettings(window, settings);
17822 settings->WantApply =
false;
17833 if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
17839 settings = ImGui::CreateNewWindowSettings(window->Name);
17840 window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings);
17842 IM_ASSERT(settings->ID == window->ID);
17843 settings->Pos =
ImVec2ih(window->Pos - window->ViewportPos);
17844 settings->Size =
ImVec2ih(window->SizeFull);
17845 settings->ViewportId = window->ViewportId;
17846 settings->ViewportPos =
ImVec2ih(window->ViewportPos);
17847 IM_ASSERT(window->DockNode == NULL || window->DockNode->ID == window->DockId);
17848 settings->DockId = window->DockId;
17849 settings->ClassId = window->WindowClass.ClassId;
17850 settings->DockOrder = window->DockOrder;
17851 settings->Collapsed = window->Collapsed;
17852 settings->IsChild =
17853 (window->RootWindow !=
17855 settings->WantDelete =
false;
17859 buf->reserve(buf->size() + g.SettingsWindows.size() * 6);
17861 settings = g.SettingsWindows.next_chunk(settings))
17863 if (settings->WantDelete)
17865 const char *settings_name = settings->GetName();
17866 buf->appendf(
"[%s][%s]\n", handler->TypeName, settings_name);
17867 if (settings->IsChild)
17869 buf->appendf(
"IsChild=1\n");
17870 buf->appendf(
"Size=%d,%d\n", settings->Size.x, settings->Size.y);
17874 if (settings->ViewportId != 0 && settings->ViewportId != ImGui::IMGUI_VIEWPORT_DEFAULT_ID)
17876 buf->appendf(
"ViewportPos=%d,%d\n", settings->ViewportPos.x, settings->ViewportPos.y);
17877 buf->appendf(
"ViewportId=0x%08X\n", settings->ViewportId);
17879 if (settings->Pos.x != 0 || settings->Pos.y != 0 ||
17880 settings->ViewportId == ImGui::IMGUI_VIEWPORT_DEFAULT_ID)
17881 buf->appendf(
"Pos=%d,%d\n", settings->Pos.x, settings->Pos.y);
17882 if (settings->Size.x != 0 || settings->Size.y != 0)
17883 buf->appendf(
"Size=%d,%d\n", settings->Size.x, settings->Size.y);
17884 buf->appendf(
"Collapsed=%d\n", settings->Collapsed);
17885 if (settings->DockId != 0)
17889 if (settings->DockOrder == -1)
17890 buf->appendf(
"DockId=0x%08X\n", settings->DockId);
17892 buf->appendf(
"DockId=0x%08X,%d\n", settings->DockId, settings->DockOrder);
17893 if (settings->ClassId != 0)
17894 buf->appendf(
"ClassId=0x%08X\n", settings->ClassId);
17905void ImGui::LocalizeRegisterEntries(
const ImGuiLocEntry *entries,
int count)
17908 for (
int n = 0; n < count; n++)
17909 g.LocalizationTable[entries[n].Key] = entries[n].Text;
17943 return g.Viewports[0];
17951 if (viewport->ID == id)
17956ImGuiViewport *ImGui::FindViewportByPlatformHandle(
void *platform_handle)
17960 if (viewport->PlatformHandle == platform_handle)
17968 (void)current_window;
17971 viewport->LastFrameActive = g.FrameCount;
17972 if (g.CurrentViewport == viewport)
17974 g.CurrentDpiScale = viewport ? viewport->DpiScale : 1.0f;
17975 g.CurrentViewport = viewport;
17976 IM_ASSERT(g.CurrentDpiScale > 0.0f &&
17977 g.CurrentDpiScale < 99.0f);
17983 if (g.CurrentViewport && g.PlatformIO.Platform_OnChangedViewport)
17984 g.PlatformIO.Platform_OnChangedViewport(g.CurrentViewport);
17990 if (window->ViewportOwned && window->Viewport->Window == window)
17991 window->Viewport->Size =
ImVec2(0.0f, 0.0f);
17993 window->Viewport = viewport;
17994 window->ViewportId = viewport->ID;
17995 window->ViewportOwned = (viewport->Window == window);
17998static bool ImGui::GetWindowAlwaysWantOwnViewport(
ImGuiWindow *window)
18003 if (g.IO.ConfigViewportsNoAutoMerge ||
18004 (window->WindowClass.ViewportFlagsOverrideSet & ImGuiViewportFlags_NoAutoMerge))
18005 if (g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
18006 if (!window->DockIsActive)
18007 if ((window->Flags &
18008 (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip)) == 0)
18009 if ((window->Flags & ImGuiWindowFlags_Popup) == 0 || (window->Flags & ImGuiWindowFlags_Modal) != 0)
18017 if (window->Viewport == viewport)
18019 if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) == 0)
18021 if ((viewport->Flags & ImGuiViewportFlags_IsMinimized) != 0)
18023 if (!viewport->GetMainRect().Contains(window->Rect()))
18025 if (GetWindowAlwaysWantOwnViewport(window))
18032 if (window_behind == window)
18034 if (window_behind->WasActive && window_behind->ViewportOwned &&
18035 !(window_behind->Flags & ImGuiWindowFlags_ChildWindow))
18036 if (window_behind->Viewport->GetMainRect().Overlaps(window->Rect()))
18042 if (window->ViewportOwned)
18043 for (
int n = 0; n < g.Windows.Size; n++)
18044 if (g.Windows[n]->Viewport == old_viewport)
18045 SetWindowViewport(g.Windows[n], viewport);
18046 SetWindowViewport(window, viewport);
18047 BringWindowToDisplayFront(window);
18053static bool ImGui::UpdateTryMergeWindowIntoHostViewports(
ImGuiWindow *window)
18056 return UpdateTryMergeWindowIntoHostViewport(window, g.Viewports[0]);
18065 IM_ASSERT(viewport->Window == NULL && (viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows));
18072 const bool translate_all_windows = (g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable) !=
18073 (g.ConfigFlagsLastFrame & ImGuiConfigFlags_ViewportsEnable);
18074 ImRect test_still_fit_rect(old_pos, old_pos + viewport->Size);
18075 ImVec2 delta_pos = new_pos - old_pos;
18077 if (translate_all_windows ||
18078 (window->Viewport == viewport && (old_size == new_size || test_still_fit_rect.Contains(window->Rect()))))
18079 TranslateWindow(window, delta_pos);
18083void ImGui::ScaleWindowsInViewport(
ImGuiViewportP *viewport,
float scale)
18086 if (viewport->Window)
18088 ScaleWindow(viewport->Window, scale);
18093 if (window->Viewport == viewport)
18094 ScaleWindow(window, scale);
18101ImGuiViewportP *ImGui::FindHoveredViewportFromPlatformWindowStack(
const ImVec2 &mouse_platform_pos)
18106 if (!(viewport->Flags & (ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_IsMinimized)) &&
18107 viewport->GetMainRect().Contains(mouse_platform_pos))
18108 if (best_candidate == NULL || best_candidate->LastFocusedStampCount < viewport->LastFocusedStampCount)
18109 best_candidate = viewport;
18110 return best_candidate;
18116static void ImGui::UpdateViewportsNewFrame()
18119 IM_ASSERT(g.PlatformIO.Viewports.Size <= g.Viewports.Size);
18123 const bool viewports_enabled = (g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable) != 0;
18124 if (viewports_enabled)
18129 const bool platform_funcs_available = viewport->PlatformWindowCreated;
18130 if (g.PlatformIO.Platform_GetWindowMinimized && platform_funcs_available)
18132 bool is_minimized = g.PlatformIO.Platform_GetWindowMinimized(viewport);
18134 viewport->Flags |= ImGuiViewportFlags_IsMinimized;
18136 viewport->Flags &= ~ImGuiViewportFlags_IsMinimized;
18142 if (g.PlatformIO.Platform_GetWindowFocus && platform_funcs_available)
18144 bool is_focused = g.PlatformIO.Platform_GetWindowFocus(viewport);
18146 viewport->Flags |= ImGuiViewportFlags_IsFocused;
18148 viewport->Flags &= ~ImGuiViewportFlags_IsFocused;
18150 focused_viewport = viewport;
18155 if (focused_viewport && g.PlatformLastFocusedViewportId != focused_viewport->ID)
18157 IMGUI_DEBUG_LOG_VIEWPORT(
18158 "[viewport] Focused viewport changed %08X -> %08X, attempting to apply our focus.\n",
18159 g.PlatformLastFocusedViewportId, focused_viewport->ID);
18160 const ImGuiViewport *prev_focused_viewport = FindViewportByID(g.PlatformLastFocusedViewportId);
18161 const bool prev_focused_has_been_destroyed =
18162 (prev_focused_viewport == NULL) || (prev_focused_viewport->PlatformWindowCreated ==
false);
18167 if (focused_viewport->LastFocusedStampCount != g.ViewportFocusedStampCount)
18168 focused_viewport->LastFocusedStampCount = ++g.ViewportFocusedStampCount;
18169 g.PlatformLastFocusedViewportId = focused_viewport->ID;
18176 const bool apply_imgui_focus_on_focused_viewport = !IsAnyMouseDown() && !prev_focused_has_been_destroyed;
18177 if (apply_imgui_focus_on_focused_viewport)
18179 focused_viewport->LastFocusedHadNavWindow |=
18180 (g.NavWindow != NULL) &&
18181 (g.NavWindow->Viewport ==
18183 ImGuiFocusRequestFlags focus_request_flags =
18184 ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild;
18185 if (focused_viewport->Window != NULL)
18186 FocusWindow(focused_viewport->Window, focus_request_flags);
18187 else if (focused_viewport->LastFocusedHadNavWindow)
18188 FocusTopMostWindowUnderOne(NULL, NULL, focused_viewport,
18189 focus_request_flags);
18191 FocusWindow(NULL, focus_request_flags);
18194 if (focused_viewport)
18195 focused_viewport->LastFocusedHadNavWindow =
18196 (g.NavWindow != NULL) && (g.NavWindow->Viewport == focused_viewport);
18203 IM_ASSERT(main_viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID);
18204 IM_ASSERT(main_viewport->Window == NULL);
18205 ImVec2 main_viewport_pos =
18206 viewports_enabled ? g.PlatformIO.Platform_GetWindowPos(main_viewport) :
ImVec2(0.0f, 0.0f);
18207 ImVec2 main_viewport_size = g.IO.DisplaySize;
18208 if (viewports_enabled && (main_viewport->Flags & ImGuiViewportFlags_IsMinimized))
18210 main_viewport_pos = main_viewport->Pos;
18212 main_viewport_size = main_viewport->Size;
18214 AddUpdateViewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, main_viewport_pos, main_viewport_size,
18215 ImGuiViewportFlags_OwnedByApp | ImGuiViewportFlags_CanHostOtherWindows);
18217 g.CurrentDpiScale = 0.0f;
18218 g.CurrentViewport = NULL;
18219 g.MouseViewport = NULL;
18220 for (
int n = 0; n < g.Viewports.Size; n++)
18226 if (n > 0 && viewport->LastFrameActive < g.FrameCount - 2)
18228 DestroyViewport(viewport);
18233 const bool platform_funcs_available = viewport->PlatformWindowCreated;
18234 if (viewports_enabled)
18239 if (!(viewport->Flags & ImGuiViewportFlags_IsMinimized) && platform_funcs_available)
18242 if (viewport->PlatformRequestMove)
18243 viewport->Pos = viewport->LastPlatformPos = g.PlatformIO.Platform_GetWindowPos(viewport);
18244 if (viewport->PlatformRequestResize)
18245 viewport->Size = viewport->LastPlatformSize = g.PlatformIO.Platform_GetWindowSize(viewport);
18250 UpdateViewportPlatformMonitor(viewport);
18254 viewport->WorkInsetMin = viewport->BuildWorkInsetMin;
18255 viewport->WorkInsetMax = viewport->BuildWorkInsetMax;
18256 viewport->BuildWorkInsetMin = viewport->BuildWorkInsetMax =
ImVec2(0.0f, 0.0f);
18257 if (g.PlatformIO.Platform_GetWindowWorkAreaInsets != NULL && platform_funcs_available)
18259 ImVec4 insets = g.PlatformIO.Platform_GetWindowWorkAreaInsets(viewport);
18260 IM_ASSERT(insets.x >= 0.0f && insets.y >= 0.0f && insets.z >= 0.0f && insets.w >= 0.0f);
18261 viewport->BuildWorkInsetMin =
ImVec2(insets.x, insets.y);
18262 viewport->BuildWorkInsetMax =
ImVec2(insets.z, insets.w);
18264 viewport->UpdateWorkRect();
18267 viewport->Alpha = 1.0f;
18271 const ImVec2 viewport_delta_pos = viewport->Pos - viewport->LastPos;
18272 if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) &&
18273 (viewport_delta_pos.x != 0.0f || viewport_delta_pos.y != 0.0f))
18274 TranslateWindowsInViewport(viewport, viewport->LastPos, viewport->Pos, viewport->LastSize, viewport->Size);
18277 float new_dpi_scale;
18278 if (g.PlatformIO.Platform_GetWindowDpiScale && platform_funcs_available)
18279 new_dpi_scale = g.PlatformIO.Platform_GetWindowDpiScale(viewport);
18280 else if (viewport->PlatformMonitor != -1)
18281 new_dpi_scale = g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
18283 new_dpi_scale = (viewport->DpiScale != 0.0f) ? viewport->DpiScale : 1.0f;
18284 IM_ASSERT(new_dpi_scale > 0.0f &&
18285 new_dpi_scale < 99.0f);
18286 if (viewport->DpiScale != 0.0f && new_dpi_scale != viewport->DpiScale)
18288 float scale_factor = new_dpi_scale / viewport->DpiScale;
18289 if (g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
18290 ScaleWindowsInViewport(viewport, scale_factor);
18301 viewport->DpiScale = new_dpi_scale;
18305 g.PlatformMonitorsFullWorkRect =
ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
18306 if (g.PlatformIO.Monitors.Size == 0)
18309 monitor->MainPos = main_viewport->Pos;
18310 monitor->MainSize = main_viewport->Size;
18311 monitor->WorkPos = main_viewport->WorkPos;
18312 monitor->WorkSize = main_viewport->WorkSize;
18313 monitor->DpiScale = main_viewport->DpiScale;
18314 g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos);
18315 g.PlatformMonitorsFullWorkRect.Add(monitor->WorkPos + monitor->WorkSize);
18319 g.FallbackMonitor = g.PlatformIO.Monitors[0];
18323 g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos);
18324 g.PlatformMonitorsFullWorkRect.Add(monitor.WorkPos + monitor.WorkSize);
18327 if (!viewports_enabled)
18329 g.MouseViewport = main_viewport;
18337 if (g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport)
18340 g.IO.MouseHoveredViewport ? (
ImGuiViewportP *)FindViewportByID(g.IO.MouseHoveredViewport) : NULL;
18341 if (viewport_hovered && (viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
18342 viewport_hovered = FindHoveredViewportFromPlatformWindowStack(
18352 viewport_hovered = FindHoveredViewportFromPlatformWindowStack(g.IO.MousePos);
18354 if (viewport_hovered != NULL)
18355 g.MouseLastHoveredViewport = viewport_hovered;
18356 else if (g.MouseLastHoveredViewport == NULL)
18357 g.MouseLastHoveredViewport = g.Viewports[0];
18363 if (g.MovingWindow && g.MovingWindow->Viewport)
18364 g.MouseViewport = g.MovingWindow->Viewport;
18366 g.MouseViewport = g.MouseLastHoveredViewport;
18376 const bool is_mouse_dragging_with_an_expected_destination = g.DragDropActive;
18377 if (is_mouse_dragging_with_an_expected_destination && viewport_hovered == NULL)
18378 viewport_hovered = g.MouseLastHoveredViewport;
18379 if (is_mouse_dragging_with_an_expected_destination || g.ActiveId == 0 || !IsAnyMouseDown())
18380 if (viewport_hovered != NULL && viewport_hovered != g.MouseViewport &&
18381 !(viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
18382 g.MouseViewport = viewport_hovered;
18384 IM_ASSERT(g.MouseViewport != NULL);
18388static void ImGui::UpdateViewportsEndFrame()
18391 g.PlatformIO.Viewports.resize(0);
18392 for (
int i = 0; i < g.Viewports.Size; i++)
18395 viewport->LastPos = viewport->Pos;
18396 viewport->LastSize = viewport->Size;
18397 if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f)
18400 if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window))
18403 IM_ASSERT(viewport->Window != NULL);
18404 g.PlatformIO.Viewports.push_back(viewport);
18406 g.Viewports[0]->ClearRequestFlags();
18412 ImGuiViewportFlags flags)
18415 IM_ASSERT(
id != 0);
18417 flags |= ImGuiViewportFlags_IsPlatformWindow;
18418 if (window != NULL)
18420 if (g.MovingWindow && g.MovingWindow->RootWindowDockTree == window)
18421 flags |= ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_NoFocusOnAppearing;
18422 if ((window->Flags & ImGuiWindowFlags_NoMouseInputs) && (window->Flags & ImGuiWindowFlags_NoNavInputs))
18423 flags |= ImGuiViewportFlags_NoInputs;
18424 if (window->Flags & ImGuiWindowFlags_NoFocusOnAppearing)
18425 flags |= ImGuiViewportFlags_NoFocusOnAppearing;
18432 ImVec2 prev_pos = viewport->Pos;
18433 ImVec2 prev_size = viewport->Size;
18434 if (!viewport->PlatformRequestMove || viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID)
18435 viewport->Pos = pos;
18436 if (!viewport->PlatformRequestResize || viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID)
18437 viewport->Size = size;
18438 viewport->Flags = flags | (viewport->Flags & (ImGuiViewportFlags_IsMinimized |
18439 ImGuiViewportFlags_IsFocused));
18440 if (prev_pos != viewport->Pos || prev_size != viewport->Size)
18441 UpdateViewportPlatformMonitor(viewport);
18448 viewport->Idx = g.Viewports.Size;
18449 viewport->Pos = viewport->LastPos = pos;
18450 viewport->Size = viewport->LastSize = size;
18451 viewport->Flags = flags;
18452 UpdateViewportPlatformMonitor(viewport);
18453 g.Viewports.push_back(viewport);
18454 g.ViewportCreatedCount++;
18455 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Add Viewport %08X '%s'\n",
id, window ? window->Name :
"<NULL>");
18460 g.DrawListSharedData.ClipRectFullscreen.x = ImMin(g.DrawListSharedData.ClipRectFullscreen.x, viewport->Pos.x);
18461 g.DrawListSharedData.ClipRectFullscreen.y = ImMin(g.DrawListSharedData.ClipRectFullscreen.y, viewport->Pos.y);
18462 g.DrawListSharedData.ClipRectFullscreen.z =
18463 ImMax(g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x);
18464 g.DrawListSharedData.ClipRectFullscreen.w =
18465 ImMax(g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y);
18469 if (viewport->PlatformMonitor != -1)
18470 viewport->DpiScale = g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
18472 viewport->DpiScale = 1.0f;
18475 viewport->Window = window;
18476 viewport->LastFrameActive = g.FrameCount;
18477 viewport->UpdateWorkRect();
18478 IM_ASSERT(window == NULL || viewport->ID == window->ID);
18480 if (window != NULL)
18481 window->ViewportOwned =
true;
18492 if (window->Viewport != viewport)
18494 window->Viewport = NULL;
18495 window->ViewportOwned =
false;
18497 if (viewport == g.MouseLastHoveredViewport)
18498 g.MouseLastHoveredViewport = NULL;
18501 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Delete Viewport %08X '%s'\n", viewport->ID,
18502 viewport->Window ? viewport->Window->Name :
"n/a");
18503 DestroyPlatformWindow(viewport);
18504 IM_ASSERT(g.PlatformIO.Viewports.contains(viewport) ==
false);
18505 IM_ASSERT(g.Viewports[viewport->Idx] == viewport);
18506 g.Viewports.erase(g.Viewports.Data + viewport->Idx);
18507 IM_DELETE(viewport);
18511static void ImGui::WindowSelectViewport(
ImGuiWindow *window)
18514 ImGuiWindowFlags flags = window->Flags;
18515 window->ViewportAllowPlatformMonitorExtend = -1;
18519 if (!(g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable))
18521 SetWindowViewport(window, main_viewport);
18524 window->ViewportOwned =
false;
18527 if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && window->Appearing)
18529 window->Viewport = NULL;
18530 window->ViewportId = 0;
18533 if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasViewport) == 0)
18536 if (window->Viewport == NULL && window->ParentWindow &&
18537 (!window->ParentWindow->IsFallbackWindow || window->ParentWindow->WasActive))
18538 window->Viewport = window->ParentWindow->Viewport;
18542 if (window->Viewport == NULL && window->ViewportId != 0)
18544 window->Viewport = (
ImGuiViewportP *)FindViewportByID(window->ViewportId);
18545 if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX)
18547 AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_None);
18551 bool lock_viewport =
false;
18552 if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasViewport)
18555 window->Viewport = (
ImGuiViewportP *)FindViewportByID(g.NextWindowData.ViewportId);
18556 window->ViewportId = g.NextWindowData.ViewportId;
18557 if (window->Viewport && (window->Flags & ImGuiWindowFlags_DockNodeHost) != 0 &&
18558 window->Viewport->Window != NULL)
18560 window->Viewport->Window = window;
18561 window->Viewport->ID = window->ViewportId = window->ID;
18563 lock_viewport =
true;
18565 else if ((flags & ImGuiWindowFlags_ChildWindow) || (flags & ImGuiWindowFlags_ChildMenu))
18568 if (window->DockNode && window->DockNode->HostWindow)
18569 IM_ASSERT(window->DockNode->HostWindow->Viewport == window->ParentWindow->Viewport);
18570 window->Viewport = window->ParentWindow->Viewport;
18572 else if (window->DockNode && window->DockNode->HostWindow)
18576 window->Viewport = window->DockNode->HostWindow->Viewport;
18578 else if (flags & ImGuiWindowFlags_Tooltip)
18580 window->Viewport = g.MouseViewport;
18582 else if (GetWindowAlwaysWantOwnViewport(window))
18584 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
18586 else if (g.MovingWindow && g.MovingWindow->RootWindowDockTree == window && IsMousePosValid())
18588 if (window->Viewport != NULL && window->Viewport->Window == window)
18590 AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
18598 bool try_to_merge_into_host_viewport =
18599 (window->Viewport && window == window->Viewport->Window && (g.ActiveId == 0 || g.ActiveIdAllowOverlap));
18600 if (try_to_merge_into_host_viewport)
18601 UpdateTryMergeWindowIntoHostViewports(window);
18605 if (window->Viewport == NULL)
18606 if (!UpdateTryMergeWindowIntoHostViewport(window, main_viewport))
18608 AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None);
18611 if (!lock_viewport)
18613 if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
18619 (flags & ImGuiWindowFlags_Tooltip) ? g.IO.MousePos : g.BeginPopupStack.back().OpenMousePos;
18620 bool use_mouse_ref = (!g.NavCursorVisible || !g.NavHighlightItemUnderNav || !g.NavWindow);
18621 bool mouse_valid = IsMousePosValid(&mouse_ref);
18622 if ((window->Appearing || (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_ChildMenu))) &&
18623 (!use_mouse_ref || mouse_valid))
18624 window->ViewportAllowPlatformMonitorExtend =
18625 FindPlatformMonitorForPos((use_mouse_ref && mouse_valid) ? mouse_ref : NavCalcPreferredRefPos());
18627 window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
18629 else if (window->Viewport && window != window->Viewport->Window && window->Viewport->Window &&
18630 !(flags & ImGuiWindowFlags_ChildWindow) && window->DockNode == NULL)
18634 const bool will_be_visible = (window->DockIsActive && !window->DockTabIsVisible) ?
false : true;
18635 if ((window->Flags & ImGuiWindowFlags_DockNodeHost) && window->Viewport->LastFrameActive < g.FrameCount &&
18639 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Window '%s' steal Viewport %08X from Window '%s'\n", window->Name,
18640 window->Viewport->ID, window->Viewport->Window->Name);
18641 window->Viewport->Window = window;
18642 window->Viewport->ID = window->ID;
18643 window->Viewport->LastNameHash = 0;
18645 else if (!UpdateTryMergeWindowIntoHostViewports(window))
18648 window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size,
18649 ImGuiViewportFlags_NoFocusOnAppearing);
18652 else if (window->ViewportAllowPlatformMonitorExtend < 0 && (flags & ImGuiWindowFlags_ChildWindow) == 0)
18656 window->ViewportAllowPlatformMonitorExtend = window->Viewport->PlatformMonitor;
18661 window->ViewportOwned = (window == window->Viewport->Window);
18662 window->ViewportId = window->Viewport->ID;
18673 bool viewport_rect_changed =
false;
18677 if (window->Viewport->PlatformRequestMove)
18679 window->Pos = window->Viewport->Pos;
18680 MarkIniSettingsDirty(window);
18682 else if (memcmp(&window->Viewport->Pos, &window->Pos,
sizeof(window->Pos)) != 0)
18684 viewport_rect_changed =
true;
18685 window->Viewport->Pos = window->Pos;
18688 if (window->Viewport->PlatformRequestResize)
18690 window->Size = window->SizeFull = window->Viewport->Size;
18691 MarkIniSettingsDirty(window);
18693 else if (memcmp(&window->Viewport->Size, &window->Size,
sizeof(window->Size)) != 0)
18695 viewport_rect_changed =
true;
18696 window->Viewport->Size = window->Size;
18698 window->Viewport->UpdateWorkRect();
18703 if (viewport_rect_changed)
18704 UpdateViewportPlatformMonitor(window->Viewport);
18707 const ImGuiViewportFlags viewport_flags_to_clear = ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon |
18708 ImGuiViewportFlags_NoDecoration |
18709 ImGuiViewportFlags_NoRendererClear;
18710 ImGuiViewportFlags viewport_flags = window->Viewport->Flags & ~viewport_flags_to_clear;
18711 ImGuiWindowFlags window_flags = window->Flags;
18712 const bool is_modal = (window_flags & ImGuiWindowFlags_Modal) != 0;
18713 const bool is_short_lived_floating_window =
18714 (window_flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0;
18715 if (window_flags & ImGuiWindowFlags_Tooltip)
18716 viewport_flags |= ImGuiViewportFlags_TopMost;
18717 if ((g.IO.ConfigViewportsNoTaskBarIcon || is_short_lived_floating_window) && !is_modal)
18718 viewport_flags |= ImGuiViewportFlags_NoTaskBarIcon;
18719 if (g.IO.ConfigViewportsNoDecoration || is_short_lived_floating_window)
18720 viewport_flags |= ImGuiViewportFlags_NoDecoration;
18734 if (is_short_lived_floating_window && !is_modal)
18735 viewport_flags |= ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoFocusOnClick;
18738 if (window->WindowClass.ViewportFlagsOverrideSet)
18739 viewport_flags |= window->WindowClass.ViewportFlagsOverrideSet;
18740 if (window->WindowClass.ViewportFlagsOverrideClear)
18741 viewport_flags &= ~window->WindowClass.ViewportFlagsOverrideClear;
18746 if (!(window_flags & ImGuiWindowFlags_NoBackground))
18747 viewport_flags |= ImGuiViewportFlags_NoRendererClear;
18749 window->Viewport->Flags = viewport_flags;
18753 if (window->WindowClass.ParentViewportId != (ImGuiID)-1)
18754 window->Viewport->ParentViewportId = window->WindowClass.ParentViewportId;
18755 else if ((window_flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && parent_window_in_stack &&
18756 (!parent_window_in_stack->IsFallbackWindow || parent_window_in_stack->WasActive))
18757 window->Viewport->ParentViewportId = parent_window_in_stack->Viewport->ID;
18759 window->Viewport->ParentViewportId = g.IO.ConfigViewportsNoDefaultParent ? 0 : IMGUI_VIEWPORT_DEFAULT_ID;
18764void ImGui::UpdatePlatformWindows()
18767 IM_ASSERT(g.FrameCountEnded == g.FrameCount &&
18768 "Forgot to call Render() or EndFrame() before UpdatePlatformWindows()?");
18769 IM_ASSERT(g.FrameCountPlatformEnded < g.FrameCount);
18770 g.FrameCountPlatformEnded = g.FrameCount;
18771 if (!(g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable))
18776 for (
int i = 1; i < g.Viewports.Size; i++)
18783 bool destroy_platform_window =
false;
18784 destroy_platform_window |= (viewport->LastFrameActive < g.FrameCount - 1);
18785 destroy_platform_window |= (viewport->Window && !IsWindowActiveAndVisible(viewport->Window));
18786 if (destroy_platform_window)
18788 DestroyPlatformWindow(viewport);
18793 if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0 || viewport->Size.y <= 0)
18797 const bool is_new_platform_window = (viewport->PlatformWindowCreated ==
false);
18798 if (is_new_platform_window)
18800 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Create Platform Window %08X '%s'\n", viewport->ID,
18801 viewport->Window ? viewport->Window->Name :
"n/a");
18802 g.PlatformIO.Platform_CreateWindow(viewport);
18803 if (g.PlatformIO.Renderer_CreateWindow != NULL)
18804 g.PlatformIO.Renderer_CreateWindow(viewport);
18805 g.PlatformWindowsCreatedCount++;
18806 viewport->LastNameHash = 0;
18807 viewport->LastPlatformPos = viewport->LastPlatformSize =
18808 ImVec2(FLT_MAX, FLT_MAX);
18810 viewport->LastRendererSize = viewport->Size;
18812 viewport->PlatformWindowCreated =
true;
18816 if ((viewport->LastPlatformPos.x != viewport->Pos.x || viewport->LastPlatformPos.y != viewport->Pos.y) &&
18817 !viewport->PlatformRequestMove)
18818 g.PlatformIO.Platform_SetWindowPos(viewport, viewport->Pos);
18819 if ((viewport->LastPlatformSize.x != viewport->Size.x || viewport->LastPlatformSize.y != viewport->Size.y) &&
18820 !viewport->PlatformRequestResize)
18821 g.PlatformIO.Platform_SetWindowSize(viewport, viewport->Size);
18822 if ((viewport->LastRendererSize.x != viewport->Size.x || viewport->LastRendererSize.y != viewport->Size.y) &&
18823 g.PlatformIO.Renderer_SetWindowSize)
18824 g.PlatformIO.Renderer_SetWindowSize(viewport, viewport->Size);
18825 viewport->LastPlatformPos = viewport->Pos;
18826 viewport->LastPlatformSize = viewport->LastRendererSize = viewport->Size;
18829 if (
ImGuiWindow *window_for_title = GetWindowForTitleDisplay(viewport->Window))
18831 const char *title_begin = window_for_title->Name;
18832 char *title_end = (
char *)(intptr_t)FindRenderedTextEnd(title_begin);
18833 const ImGuiID title_hash = ImHashStr(title_begin, title_end - title_begin);
18834 if (viewport->LastNameHash != title_hash)
18836 char title_end_backup_c = *title_end;
18838 g.PlatformIO.Platform_SetWindowTitle(viewport, title_begin);
18839 *title_end = title_end_backup_c;
18840 viewport->LastNameHash = title_hash;
18845 if (viewport->LastAlpha != viewport->Alpha && g.PlatformIO.Platform_SetWindowAlpha)
18846 g.PlatformIO.Platform_SetWindowAlpha(viewport, viewport->Alpha);
18847 viewport->LastAlpha = viewport->Alpha;
18851 if (g.PlatformIO.Platform_UpdateWindow)
18852 g.PlatformIO.Platform_UpdateWindow(viewport);
18854 if (is_new_platform_window)
18858 if (g.FrameCount < 3)
18859 viewport->Flags |= ImGuiViewportFlags_NoFocusOnAppearing;
18862 g.PlatformIO.Platform_ShowWindow(viewport);
18866 if (viewport->LastFocusedStampCount != g.ViewportFocusedStampCount)
18867 viewport->LastFocusedStampCount = ++g.ViewportFocusedStampCount;
18871 viewport->ClearRequestFlags();
18888void ImGui::RenderPlatformWindowsDefault(
void *platform_render_arg,
void *renderer_render_arg)
18892 for (
int i = 1; i < platform_io.Viewports.Size; i++)
18895 if (viewport->Flags & ImGuiViewportFlags_IsMinimized)
18897 if (platform_io.Platform_RenderWindow)
18898 platform_io.Platform_RenderWindow(viewport, platform_render_arg);
18899 if (platform_io.Renderer_RenderWindow)
18900 platform_io.Renderer_RenderWindow(viewport, renderer_render_arg);
18902 for (
int i = 1; i < platform_io.Viewports.Size; i++)
18905 if (viewport->Flags & ImGuiViewportFlags_IsMinimized)
18907 if (platform_io.Platform_SwapBuffers)
18908 platform_io.Platform_SwapBuffers(viewport, platform_render_arg);
18909 if (platform_io.Renderer_SwapBuffers)
18910 platform_io.Renderer_SwapBuffers(viewport, renderer_render_arg);
18914static int ImGui::FindPlatformMonitorForPos(
const ImVec2 &pos)
18917 for (
int monitor_n = 0; monitor_n < g.PlatformIO.Monitors.Size; monitor_n++)
18920 if (
ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize).Contains(pos))
18929static int ImGui::FindPlatformMonitorForRect(
const ImRect &rect)
18933 const int monitor_count = g.PlatformIO.Monitors.Size;
18934 if (monitor_count <= 1)
18935 return monitor_count - 1;
18939 const float surface_threshold = ImMax(rect.GetWidth() * rect.GetHeight() * 0.5f, 1.0f);
18940 int best_monitor_n = 0;
18941 float best_monitor_surface = 0.001f;
18943 for (
int monitor_n = 0; monitor_n < g.PlatformIO.Monitors.Size && best_monitor_surface < surface_threshold;
18947 const ImRect monitor_rect =
ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize);
18948 if (monitor_rect.Contains(rect))
18950 ImRect overlapping_rect = rect;
18951 overlapping_rect.ClipWithFull(monitor_rect);
18952 float overlapping_surface = overlapping_rect.GetWidth() * overlapping_rect.GetHeight();
18953 if (overlapping_surface < best_monitor_surface)
18955 best_monitor_surface = overlapping_surface;
18956 best_monitor_n = monitor_n;
18958 return best_monitor_n;
18963static void ImGui::UpdateViewportPlatformMonitor(
ImGuiViewportP *viewport)
18965 viewport->PlatformMonitor = (short)FindPlatformMonitorForRect(viewport->GetMainRect());
18973 int monitor_idx = viewport->PlatformMonitor;
18974 if (monitor_idx >= 0 && monitor_idx < g.PlatformIO.Monitors.Size)
18975 return &g.PlatformIO.Monitors[monitor_idx];
18976 return &g.FallbackMonitor;
18982 if (viewport->PlatformWindowCreated)
18984 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Destroy Platform Window %08X '%s'\n", viewport->ID,
18985 viewport->Window ? viewport->Window->Name :
"n/a");
18986 if (g.PlatformIO.Renderer_DestroyWindow)
18987 g.PlatformIO.Renderer_DestroyWindow(viewport);
18988 if (g.PlatformIO.Platform_DestroyWindow)
18989 g.PlatformIO.Platform_DestroyWindow(viewport);
18990 IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL);
18994 if (viewport->ID != IMGUI_VIEWPORT_DEFAULT_ID)
18995 viewport->PlatformWindowCreated =
false;
18999 IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL &&
19000 viewport->PlatformHandle == NULL);
19002 viewport->RendererUserData = viewport->PlatformUserData = viewport->PlatformHandle = NULL;
19003 viewport->ClearRequestFlags();
19006void ImGui::DestroyPlatformWindows()
19015 DestroyPlatformWindow(viewport);
19090enum ImGuiDockRequestType
19092 ImGuiDockRequestType_None = 0,
19093 ImGuiDockRequestType_Dock,
19094 ImGuiDockRequestType_Undock,
19095 ImGuiDockRequestType_Split
19100 ImGuiDockRequestType Type;
19105 ImGuiDir DockSplitDir;
19106 float DockSplitRatio;
19107 bool DockSplitOuter;
19113 Type = ImGuiDockRequestType_None;
19114 DockTargetWindow = DockPayload = UndockTargetWindow = NULL;
19115 DockTargetNode = UndockTargetNode = NULL;
19116 DockSplitDir = ImGuiDir_None;
19117 DockSplitRatio = 0.5f;
19118 DockSplitOuter =
false;
19125 bool IsDropAllowed;
19126 bool IsCenterAvailable;
19127 bool IsSidesAvailable;
19128 bool IsSplitDirExplicit;
19132 ImRect DropRectsDraw[ImGuiDir_COUNT +
19137 IsDropAllowed = IsCenterAvailable = IsSidesAvailable = IsSplitDirExplicit =
false;
19139 SplitDir = ImGuiDir_None;
19141 for (
int n = 0; n < IM_ARRAYSIZE(DropRectsDraw); n++)
19142 DropRectsDraw[n] =
ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
19150 ImGuiID ParentNodeId;
19151 ImGuiID ParentWindowId;
19152 ImGuiID SelectedTabId;
19153 signed char SplitAxis;
19162 memset(
this, 0,
sizeof(*
this));
19163 SplitAxis = ImGuiAxis_None;
19178static void DockContextPruneUnusedSettingsNodes(
ImGuiContext *ctx);
19181 int node_settings_count);
19182static void DockContextBuildAddWindowsToNodes(
ImGuiContext *ctx, ImGuiID root_id);
19189static void DockNodeApplyPosSizeToWindows(
ImGuiDockNode *node);
19194static void DockNodeUpdateFlagsAndCollapse(
ImGuiDockNode *node);
19195static void DockNodeUpdateHasCentralNodeChild(
ImGuiDockNode *node);
19205 bool is_explicit_target,
bool is_outer_docking);
19209 ImVec2 *out_window_menu_button_pos,
ImVec2 *out_close_button_pos);
19210static void DockNodeCalcSplitRects(
ImVec2 &pos_old,
ImVec2 &size_old,
ImVec2 &pos_new,
ImVec2 &size_new, ImGuiDir dir,
19211 ImVec2 size_new_desired);
19212static bool DockNodeCalcDropRectsAndTestMousePos(
const ImRect &parent, ImGuiDir dir,
ImRect &out_draw,
19213 bool outer_docking,
ImVec2 *test_mouse_pos);
19214static const char *DockNodeGetHostWindowTitle(
ImGuiDockNode *node,
char *buf,
int buf_size)
19216 ImFormatString(buf, buf_size,
"##DockNode_%02X", node->ID);
19219static int DockNodeGetTabOrder(
ImGuiWindow *window);
19223 int split_first_child,
float split_ratio,
ImGuiDockNode *new_node);
19227static void DockNodeTreeUpdateSplitter(
ImGuiDockNode *node);
19232static void DockSettingsRenameNodeReferences(ImGuiID old_node_id, ImGuiID new_node_id);
19233static void DockSettingsRemoveNodeReferences(ImGuiID *node_ids,
int node_ids_count);
19277 ini_handler.TypeName =
"Docking";
19278 ini_handler.TypeHash = ImHashStr(
"Docking");
19279 ini_handler.ClearAllFn = DockSettingsHandler_ClearAll;
19280 ini_handler.ReadInitFn = DockSettingsHandler_ClearAll;
19281 ini_handler.ReadOpenFn = DockSettingsHandler_ReadOpen;
19282 ini_handler.ReadLineFn = DockSettingsHandler_ReadLine;
19283 ini_handler.ApplyAllFn = DockSettingsHandler_ApplyAll;
19284 ini_handler.WriteAllFn = DockSettingsHandler_WriteAll;
19285 g.SettingsHandlers.push_back(ini_handler);
19287 g.DockNodeWindowMenuHandler = &DockNodeWindowMenuHandler_Default;
19293 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
19298void ImGui::DockContextClearNodes(
ImGuiContext *ctx, ImGuiID root_id,
bool clear_settings_refs)
19301 IM_ASSERT(ctx == GImGui);
19302 DockBuilderRemoveNodeDockedWindows(root_id, clear_settings_refs);
19303 DockBuilderRemoveNodeChildNodes(root_id);
19313 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextRebuildNodes\n");
19314 SaveIniSettingsToMemory();
19315 ImGuiID root_id = 0;
19316 DockContextClearNodes(ctx, root_id,
false);
19317 DockContextBuildNodesFromSettings(ctx, dc->NodesSettings.Data, dc->NodesSettings.Size);
19318 DockContextBuildAddWindowsToNodes(ctx, root_id);
19322void ImGui::DockContextNewFrameUpdateUndocking(
ImGuiContext *ctx)
19326 if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
19328 if (dc->Nodes.Data.Size > 0 || dc->Requests.Size > 0)
19329 DockContextClearNodes(ctx, 0,
true);
19334 if (g.IO.ConfigDockingNoSplit)
19335 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
19337 if (node->IsRootNode() && node->IsSplitNode())
19339 DockBuilderRemoveNodeChildNodes(node->ID);
19345 if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
19346 dc->WantFullRebuild =
true;
19348 if (dc->WantFullRebuild)
19350 DockContextRebuildNodes(ctx);
19351 dc->WantFullRebuild =
false;
19358 if (req.Type == ImGuiDockRequestType_Undock && req.UndockTargetWindow)
19359 DockContextProcessUndockWindow(ctx, req.UndockTargetWindow);
19360 else if (req.Type == ImGuiDockRequestType_Undock && req.UndockTargetNode)
19361 DockContextProcessUndockNode(ctx, req.UndockTargetNode);
19366void ImGui::DockContextNewFrameUpdateDocking(
ImGuiContext *ctx)
19370 if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
19377 g.DebugHoveredDockNode = NULL;
19378 if (
ImGuiWindow *hovered_window = g.HoveredWindowUnderMovingWindow)
19380 if (hovered_window->DockNodeAsHost)
19381 g.DebugHoveredDockNode = DockNodeTreeFindVisibleNodeByPos(hovered_window->DockNodeAsHost, g.IO.MousePos);
19382 else if (hovered_window->RootWindow->DockNode)
19383 g.DebugHoveredDockNode = hovered_window->RootWindow->DockNode;
19388 if (req.Type == ImGuiDockRequestType_Dock)
19389 DockContextProcessDock(ctx, &req);
19390 dc->Requests.resize(0);
19395 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
19397 if (node->IsFloatingNode())
19398 DockNodeUpdate(node);
19406 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
19408 if (node->LastFrameActive == g.FrameCount && node->IsVisible && node->HostWindow && node->IsLeafNode() &&
19409 !node->IsBgDrawnThisFrame)
19411 ImRect bg_rect(node->Pos +
ImVec2(0.0f, GetFrameHeight()), node->Pos + node->Size);
19412 ImDrawFlags bg_rounding_flags =
19413 CalcRoundingFlagsForRectInRect(bg_rect, node->HostWindow->Rect(), g.Style.DockingSeparatorSize);
19414 node->HostWindow->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
19415 node->HostWindow->DrawList->AddRectFilled(bg_rect.Min, bg_rect.Max, node->LastBgColor,
19416 node->HostWindow->WindowRounding, bg_rounding_flags);
19422 return (
ImGuiDockNode *)ctx->DockContext.Nodes.GetVoidPtr(
id);
19431 ImGuiID
id = 0x0001;
19432 while (DockContextFindNodeByID(ctx,
id) != NULL)
19443 id = DockContextGenNodeID(ctx);
19445 IM_ASSERT(DockContextFindNodeByID(ctx,
id) == NULL);
19448 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextAddNode 0x%08X\n",
id);
19450 ctx->DockContext.Nodes.SetVoidPtr(node->ID, node);
19459 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextRemoveNode 0x%08X\n", node->ID);
19460 IM_ASSERT(DockContextFindNodeByID(ctx, node->ID) == node);
19461 IM_ASSERT(node->ChildNodes[0] == NULL && node->ChildNodes[1] == NULL);
19462 IM_ASSERT(node->Windows.Size == 0);
19464 if (node->HostWindow)
19465 node->HostWindow->DockNodeAsHost = NULL;
19468 const bool merge = (merge_sibling_into_parent_node && parent_node != NULL);
19471 IM_ASSERT(parent_node->ChildNodes[0] == node || parent_node->ChildNodes[1] == node);
19473 (parent_node->ChildNodes[0] == node ? parent_node->ChildNodes[1] : parent_node->ChildNodes[0]);
19474 DockNodeTreeMerge(&g, parent_node, sibling_node);
19478 for (
int n = 0; parent_node && n < IM_ARRAYSIZE(parent_node->ChildNodes); n++)
19479 if (parent_node->ChildNodes[n] == node)
19480 node->ParentNode->ChildNodes[n] = NULL;
19481 dc->Nodes.SetVoidPtr(node->ID, NULL);
19486static int IMGUI_CDECL DockNodeComparerDepthMostFirst(
const void *lhs,
const void *rhs)
19490 return ImGui::DockNodeGetDepth(b) - ImGui::DockNodeGetDepth(a);
19497 int CountWindows, CountChildWindows, CountChildNodes;
19501 CountWindows = CountChildWindows = CountChildNodes = 0;
19507static void ImGui::DockContextPruneUnusedSettingsNodes(
ImGuiContext *ctx)
19511 IM_ASSERT(g.Windows.Size == 0);
19514 pool.Reserve(dc->NodesSettings.Size);
19517 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
19521 pool.GetOrAddByKey(settings->ID)->RootId = parent_data ? parent_data->RootId : settings->ID;
19522 if (settings->ParentNodeId)
19523 pool.GetOrAddByKey(settings->ParentNodeId)->CountChildNodes++;
19529 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
19532 if (settings->ParentWindowId != 0)
19533 if (
ImGuiWindowSettings *window_settings = FindWindowSettingsByID(settings->ParentWindowId))
19534 if (window_settings->DockId)
19536 data->CountChildNodes++;
19542 settings = g.SettingsWindows.next_chunk(settings))
19543 if (ImGuiID dock_id = settings->DockId)
19546 data->CountWindows++;
19548 (data->RootId == dock_id) ? data : pool.GetByKey(data->RootId))
19549 data_root->CountChildWindows++;
19553 for (
int settings_n = 0; settings_n < dc->NodesSettings.Size; settings_n++)
19557 if (data->CountWindows > 1)
19561 bool remove =
false;
19562 remove |= (data->CountWindows == 1 && settings->ParentNodeId == 0 && data->CountChildNodes == 0 &&
19563 !(settings->Flags & ImGuiDockNodeFlags_CentralNode));
19564 remove |= (data->CountWindows == 0 && settings->ParentNodeId == 0 &&
19565 data->CountChildNodes == 0);
19566 remove |= (data_root->CountChildWindows == 0);
19569 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextPruneUnusedSettingsNodes: Prune 0x%08X\n", settings->ID);
19570 DockSettingsRemoveNodeReferences(&settings->ID, 1);
19577 int node_settings_count)
19580 for (
int node_n = 0; node_n < node_settings_count; node_n++)
19583 if (settings->ID == 0)
19585 ImGuiDockNode *node = DockContextAddNode(ctx, settings->ID);
19586 node->ParentNode = settings->ParentNodeId ? DockContextFindNodeByID(ctx, settings->ParentNodeId) : NULL;
19587 node->Pos =
ImVec2(settings->Pos.x, settings->Pos.y);
19588 node->Size =
ImVec2(settings->Size.x, settings->Size.y);
19589 node->SizeRef =
ImVec2(settings->SizeRef.x, settings->SizeRef.y);
19590 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_DockNode;
19591 if (node->ParentNode && node->ParentNode->ChildNodes[0] == NULL)
19592 node->ParentNode->ChildNodes[0] = node;
19593 else if (node->ParentNode && node->ParentNode->ChildNodes[1] == NULL)
19594 node->ParentNode->ChildNodes[1] = node;
19595 node->SelectedTabId = settings->SelectedTabId;
19596 node->SplitAxis = (ImGuiAxis)settings->SplitAxis;
19597 node->SetLocalFlags(settings->Flags & ImGuiDockNodeFlags_SavedFlagsMask_);
19602 char host_window_title[20];
19605 FindWindowByName(DockNodeGetHostWindowTitle(root_node, host_window_title, IM_ARRAYSIZE(host_window_title)));
19609void ImGui::DockContextBuildAddWindowsToNodes(
ImGuiContext *ctx, ImGuiID root_id)
19615 if (window->DockId == 0 || window->LastFrameActive < g.FrameCount - 1)
19617 if (window->DockNode != NULL)
19620 ImGuiDockNode *node = DockContextFindNodeByID(ctx, window->DockId);
19621 IM_ASSERT(node != NULL);
19622 if (root_id == 0 || DockNodeGetRootNode(node)->ID == root_id)
19623 DockNodeAddWindow(node, window,
true);
19641 ImGuiWindow *payload, ImGuiDir split_dir,
float split_ratio,
bool split_outer)
19643 IM_ASSERT(target != payload);
19645 req.Type = ImGuiDockRequestType_Dock;
19646 req.DockTargetWindow = target;
19647 req.DockTargetNode = target_node;
19648 req.DockPayload = payload;
19649 req.DockSplitDir = split_dir;
19650 req.DockSplitRatio = split_ratio;
19651 req.DockSplitOuter = split_outer;
19652 ctx->DockContext.Requests.push_back(req);
19658 req.Type = ImGuiDockRequestType_Undock;
19659 req.UndockTargetWindow = window;
19660 ctx->DockContext.Requests.push_back(req);
19666 req.Type = ImGuiDockRequestType_Undock;
19667 req.UndockTargetNode = node;
19668 ctx->DockContext.Requests.push_back(req);
19675 if (req.DockTargetNode == node)
19676 req.Type = ImGuiDockRequestType_None;
19681 IM_ASSERT((req->Type == ImGuiDockRequestType_Dock && req->DockPayload != NULL) ||
19682 (req->Type == ImGuiDockRequestType_Split && req->DockPayload == NULL));
19683 IM_ASSERT(req->DockTargetWindow != NULL || req->DockTargetNode != NULL);
19689 ImGuiWindow *target_window = req->DockTargetWindow;
19691 if (payload_window)
19692 IMGUI_DEBUG_LOG_DOCKING(
19693 "[docking] DockContextProcessDock node 0x%08X target '%s' dock window '%s', split_dir %d\n",
19694 node ? node->ID : 0, target_window ? target_window->Name :
"NULL", payload_window->Name, req->DockSplitDir);
19696 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessDock node 0x%08X, split_dir %d\n", node ? node->ID : 0,
19697 req->DockSplitDir);
19700 ImGuiID next_selected_id = 0;
19702 if (payload_window)
19704 payload_node = payload_window->DockNodeAsHost;
19705 payload_window->DockNodeAsHost = NULL;
19707 if (payload_node && payload_node->IsLeafNode())
19708 next_selected_id = payload_node->TabBar->NextSelectedTabId ? payload_node->TabBar->NextSelectedTabId
19709 : payload_node->TabBar->SelectedTabId;
19710 if (payload_node == NULL)
19711 next_selected_id = payload_window->TabId;
19718 IM_ASSERT(node->LastFrameAlive <= g.FrameCount);
19719 if (node && target_window && node == target_window->DockNodeAsHost)
19720 IM_ASSERT(node->Windows.Size > 0 || node->IsSplitNode() || node->IsCentralNode());
19725 node = DockContextAddNode(ctx, 0);
19726 node->Pos = target_window->Pos;
19727 node->Size = target_window->Size;
19728 if (target_window->DockNodeAsHost == NULL)
19730 DockNodeAddWindow(node, target_window,
true);
19731 node->TabBar->Tabs[0].Flags &= ~ImGuiTabItemFlags_Unsorted;
19732 target_window->DockIsActive =
true;
19736 ImGuiDir split_dir = req->DockSplitDir;
19737 if (split_dir != ImGuiDir_None)
19740 const ImGuiAxis split_axis =
19741 (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
19742 const int split_inheritor_child_idx = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up)
19745 const float split_ratio = req->DockSplitRatio;
19746 DockNodeTreeSplit(ctx, node, split_axis, split_inheritor_child_idx, split_ratio,
19748 ImGuiDockNode *new_node = node->ChildNodes[split_inheritor_child_idx ^ 1];
19749 new_node->HostWindow = node->HostWindow;
19752 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_HiddenTabBar);
19754 if (node != payload_node)
19758 if (node->Windows.Size > 0 && node->TabBar == NULL)
19760 DockNodeAddTabBar(node);
19761 for (
int n = 0; n < node->Windows.Size; n++)
19762 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_None, node->Windows[n]);
19765 if (payload_node != NULL)
19768 if (payload_node->IsSplitNode())
19770 if (node->Windows.Size > 0)
19776 IM_ASSERT(payload_node->OnlyNodeWithWindows !=
19779 ImGuiDockNode *visible_node = payload_node->OnlyNodeWithWindows;
19780 if (visible_node->TabBar)
19781 IM_ASSERT(visible_node->TabBar->Tabs.Size > 0);
19782 DockNodeMoveWindows(node, visible_node);
19783 DockNodeMoveWindows(visible_node, node);
19784 DockSettingsRenameNodeReferences(node->ID, visible_node->ID);
19786 if (node->IsCentralNode())
19790 ImGuiDockNode *last_focused_node = DockContextFindNodeByID(ctx, payload_node->LastFocusedNodeId);
19791 IM_ASSERT(last_focused_node != NULL);
19792 ImGuiDockNode *last_focused_root_node = DockNodeGetRootNode(last_focused_node);
19793 IM_ASSERT(last_focused_root_node == DockNodeGetRootNode(payload_node));
19794 last_focused_node->SetLocalFlags(last_focused_node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
19795 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_CentralNode);
19796 last_focused_root_node->CentralNode = last_focused_node;
19799 IM_ASSERT(node->Windows.Size == 0);
19800 DockNodeMoveChildNodes(node, payload_node);
19804 const ImGuiID payload_dock_id = payload_node->ID;
19805 DockNodeMoveWindows(node, payload_node);
19806 DockSettingsRenameNodeReferences(payload_dock_id, node->ID);
19808 DockContextRemoveNode(ctx, payload_node,
true);
19810 else if (payload_window)
19813 const ImGuiID payload_dock_id = payload_window->DockId;
19814 node->VisibleWindow = payload_window;
19815 DockNodeAddWindow(node, payload_window,
true);
19816 if (payload_dock_id != 0)
19817 DockSettingsRenameNodeReferences(payload_dock_id, node->ID);
19823 node->WantHiddenTabBarUpdate =
true;
19828 tab_bar->NextSelectedTabId = next_selected_id;
19829 MarkIniSettingsDirty();
19842 if (ref_viewport == NULL)
19846 ImVec2 max_size = ImTrunc(ref_viewport->WorkSize * 0.90f);
19847 if (g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
19850 max_size = ImTrunc(monitor->WorkSize * 0.90f);
19852 return ImMin(size, max_size);
19855void ImGui::DockContextProcessUndockWindow(
ImGuiContext *ctx,
ImGuiWindow *window,
bool clear_persistent_docking_ref)
19858 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessUndockWindow window '%s', clear_persistent_docking_ref = %d\n",
19859 window->Name, clear_persistent_docking_ref);
19860 if (window->DockNode)
19861 DockNodeRemoveWindow(window->DockNode, window, clear_persistent_docking_ref ? 0 : window->DockId);
19863 window->DockId = 0;
19864 window->Collapsed =
false;
19865 window->DockIsActive =
false;
19866 window->DockNodeIsVisible = window->DockTabIsVisible =
false;
19867 window->Size = window->SizeFull = FixLargeWindowsWhenUndocking(window->SizeFull, window->Viewport);
19869 MarkIniSettingsDirty();
19875 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockContextProcessUndockNode node %08X\n", node->ID);
19876 IM_ASSERT(node->IsLeafNode());
19877 IM_ASSERT(node->Windows.Size >= 1);
19879 if (node->IsRootNode() || node->IsCentralNode())
19884 new_node->Pos = node->Pos;
19885 new_node->Size = node->Size;
19886 new_node->SizeRef = node->SizeRef;
19887 DockNodeMoveWindows(new_node, node);
19888 DockSettingsRenameNodeReferences(node->ID, new_node->ID);
19894 IM_ASSERT(node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node);
19895 int index_in_parent = (node->ParentNode->ChildNodes[0] == node) ? 0 : 1;
19896 node->ParentNode->ChildNodes[index_in_parent] = NULL;
19897 DockNodeTreeMerge(ctx, node->ParentNode, node->ParentNode->ChildNodes[index_in_parent ^ 1]);
19898 node->ParentNode->AuthorityForViewport =
19899 ImGuiDataAuthority_Window;
19901 node->ParentNode = NULL;
19905 window->Flags &= ~ImGuiWindowFlags_ChildWindow;
19906 if (window->ParentWindow)
19907 window->ParentWindow->DC.ChildWindows.find_erase(window);
19908 UpdateWindowParentAndRootLinks(window, window->Flags, NULL);
19910 node->AuthorityForPos = node->AuthorityForSize = ImGuiDataAuthority_DockNode;
19911 node->Size = FixLargeWindowsWhenUndocking(node->Size, node->Windows[0]->Viewport);
19912 node->WantMouseMove =
true;
19913 MarkIniSettingsDirty();
19919 ImGuiDir split_dir,
bool split_outer,
ImVec2 *out_pos)
19921 if (target != NULL && target_node == NULL)
19922 target_node = target->DockNode;
19926 if (target_node && target_node->ParentNode == NULL && target_node->IsCentralNode() && split_dir != ImGuiDir_None)
19927 split_outer =
true;
19929 DockNodePreviewDockSetup(target, target_node, payload_window, payload_node, &split_data,
false, split_outer);
19930 if (split_data.DropRectsDraw[split_dir + 1].IsInverted())
19932 *out_pos = split_data.DropRectsDraw[split_dir + 1].GetCenter();
19969ImGuiDockNode::ImGuiDockNode(ImGuiID
id)
19972 SharedFlags = LocalFlags = LocalFlagsInWindows = MergedFlags = ImGuiDockNodeFlags_None;
19973 ParentNode = ChildNodes[0] = ChildNodes[1] = NULL;
19975 SplitAxis = ImGuiAxis_None;
19977 State = ImGuiDockNodeState_Unknown;
19978 LastBgColor = IM_COL32_WHITE;
19979 HostWindow = VisibleWindow = NULL;
19980 CentralNode = OnlyNodeWithWindows = NULL;
19981 CountNodeWithWindows = 0;
19982 LastFrameAlive = LastFrameActive = LastFrameFocused = -1;
19983 LastFocusedNodeId = 0;
19985 WantCloseTabId = 0;
19987 AuthorityForPos = AuthorityForSize = ImGuiDataAuthority_DockNode;
19988 AuthorityForViewport = ImGuiDataAuthority_Auto;
19990 IsFocused = HasCloseButton = HasWindowMenuButton = HasCentralNodeChild =
false;
19991 IsBgDrawnThisFrame =
false;
19992 WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle =
false;
19995ImGuiDockNode::~ImGuiDockNode()
19999 ChildNodes[0] = ChildNodes[1] = NULL;
20002int ImGui::DockNodeGetTabOrder(
ImGuiWindow *window)
20005 if (tab_bar == NULL)
20007 ImGuiTabItem *tab = TabBarFindTabByID(tab_bar, window->TabId);
20008 return tab ? TabBarGetTabOrder(tab_bar, tab) : -1;
20011static void DockNodeHideWindowDuringHostWindowCreation(
ImGuiWindow *window)
20013 window->Hidden =
true;
20014 window->HiddenFramesCanSkipItems = window->Active ? 1 : 2;
20021 if (window->DockNode)
20024 IM_ASSERT(window->DockNode->ID != node->ID);
20025 DockNodeRemoveWindow(window->DockNode, window, 0);
20027 IM_ASSERT(window->DockNode == NULL || window->DockNodeAsHost == NULL);
20028 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockNodeAddWindow node 0x%08X window '%s'\n", node->ID, window->Name);
20033 if (node->HostWindow == NULL && node->Windows.Size == 1 && node->Windows[0]->WasActive ==
false)
20034 DockNodeHideWindowDuringHostWindowCreation(node->Windows[0]);
20036 node->Windows.push_back(window);
20037 node->WantHiddenTabBarUpdate =
true;
20038 window->DockNode = node;
20039 window->DockId = node->ID;
20040 window->DockIsActive = (node->Windows.Size > 1);
20041 window->DockTabWantClose =
false;
20046 if (node->HostWindow == NULL && node->IsFloatingNode())
20048 if (node->AuthorityForPos == ImGuiDataAuthority_Auto)
20049 node->AuthorityForPos = ImGuiDataAuthority_Window;
20050 if (node->AuthorityForSize == ImGuiDataAuthority_Auto)
20051 node->AuthorityForSize = ImGuiDataAuthority_Window;
20052 if (node->AuthorityForViewport == ImGuiDataAuthority_Auto)
20053 node->AuthorityForViewport = ImGuiDataAuthority_Window;
20057 if (add_to_tab_bar)
20059 if (node->TabBar == NULL)
20061 DockNodeAddTabBar(node);
20062 node->TabBar->SelectedTabId = node->TabBar->NextSelectedTabId = node->SelectedTabId;
20065 for (
int n = 0; n < node->Windows.Size - 1; n++)
20066 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_None, node->Windows[n]);
20068 TabBarAddTab(node->TabBar, ImGuiTabItemFlags_Unsorted, window);
20071 DockNodeUpdateVisibleFlag(node);
20075 if (node->HostWindow)
20076 UpdateWindowParentAndRootLinks(window, window->Flags | ImGuiWindowFlags_ChildWindow, node->HostWindow);
20082 IM_ASSERT(window->DockNode == node);
20085 IM_ASSERT(save_dock_id == 0 || save_dock_id == node->ID);
20086 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockNodeRemoveWindow node 0x%08X window '%s'\n", node->ID, window->Name);
20088 window->DockNode = NULL;
20089 window->DockIsActive = window->DockTabWantClose =
false;
20090 window->DockId = save_dock_id;
20091 window->Flags &= ~ImGuiWindowFlags_ChildWindow;
20092 if (window->ParentWindow)
20093 window->ParentWindow->DC.ChildWindows.find_erase(window);
20094 UpdateWindowParentAndRootLinks(window, window->Flags, NULL);
20096 if (node->HostWindow && node->HostWindow->ViewportOwned)
20100 window->Viewport = NULL;
20101 window->ViewportId = 0;
20102 window->ViewportOwned =
false;
20103 window->Hidden =
true;
20107 bool erased =
false;
20108 for (
int n = 0; n < node->Windows.Size; n++)
20109 if (node->Windows[n] == window)
20111 node->Windows.erase(node->Windows.Data + n);
20117 if (node->VisibleWindow == window)
20118 node->VisibleWindow = NULL;
20121 node->WantHiddenTabBarUpdate =
true;
20124 TabBarRemoveTab(node->TabBar, window->TabId);
20125 const int tab_count_threshold_for_tab_bar = node->IsCentralNode() ? 1 : 2;
20126 if (node->Windows.Size < tab_count_threshold_for_tab_bar)
20127 DockNodeRemoveTabBar(node);
20130 if (node->Windows.Size == 0 && !node->IsCentralNode() && !node->IsDockSpace() && window->DockId != node->ID)
20133 DockContextRemoveNode(&g, node,
true);
20137 if (node->Windows.Size == 1 && !node->IsCentralNode() && node->HostWindow)
20139 ImGuiWindow *remaining_window = node->Windows[0];
20141 remaining_window->Collapsed = node->HostWindow->Collapsed;
20146 DockNodeUpdateVisibleFlag(node);
20151 IM_ASSERT(dst_node->Windows.Size == 0);
20152 dst_node->ChildNodes[0] = src_node->ChildNodes[0];
20153 dst_node->ChildNodes[1] = src_node->ChildNodes[1];
20154 if (dst_node->ChildNodes[0])
20155 dst_node->ChildNodes[0]->ParentNode = dst_node;
20156 if (dst_node->ChildNodes[1])
20157 dst_node->ChildNodes[1]->ParentNode = dst_node;
20158 dst_node->SplitAxis = src_node->SplitAxis;
20159 dst_node->SizeRef = src_node->SizeRef;
20160 src_node->ChildNodes[0] = src_node->ChildNodes[1] = NULL;
20166 IM_ASSERT(src_node && dst_node && dst_node != src_node);
20168 if (src_tab_bar != NULL)
20169 IM_ASSERT(src_node->Windows.Size <= src_node->TabBar->Tabs.Size);
20172 bool move_tab_bar = (src_tab_bar != NULL) && (dst_node->TabBar == NULL);
20175 dst_node->TabBar = src_node->TabBar;
20176 src_node->TabBar = NULL;
20182 window->DockNode = NULL;
20183 window->DockIsActive =
false;
20184 DockNodeAddWindow(dst_node, window, !move_tab_bar);
20186 src_node->Windows.clear();
20188 if (!move_tab_bar && src_node->TabBar)
20190 if (dst_node->TabBar)
20191 dst_node->TabBar->SelectedTabId = src_node->TabBar->SelectedTabId;
20192 DockNodeRemoveTabBar(src_node);
20196static void ImGui::DockNodeApplyPosSizeToWindows(
ImGuiDockNode *node)
20200 SetWindowPos(window, node->Pos, ImGuiCond_Always);
20202 SetWindowSize(window, node->Size, ImGuiCond_Always);
20206static void ImGui::DockNodeHideHostWindow(
ImGuiDockNode *node)
20208 if (node->HostWindow)
20210 if (node->HostWindow->DockNodeAsHost == node)
20211 node->HostWindow->DockNodeAsHost = NULL;
20212 node->HostWindow = NULL;
20215 if (node->Windows.Size == 1)
20217 node->VisibleWindow = node->Windows[0];
20218 node->Windows[0]->DockIsActive =
false;
20222 DockNodeRemoveTabBar(node);
20230 int CountNodesWithWindows;
20235 memset(
this, 0,
sizeof(*
this));
20241 if (node->Windows.Size > 0)
20243 if (info->FirstNodeWithWindows == NULL)
20244 info->FirstNodeWithWindows = node;
20245 info->CountNodesWithWindows++;
20247 if (node->IsCentralNode())
20249 IM_ASSERT(info->CentralNode == NULL);
20250 IM_ASSERT(node->IsLeafNode() &&
20251 "If you get this assert: please submit .ini file + repro of actions leading to this.");
20252 info->CentralNode = node;
20254 if (info->CountNodesWithWindows > 1 && info->CentralNode != NULL)
20256 if (node->ChildNodes[0])
20257 DockNodeFindInfo(node->ChildNodes[0], info);
20258 if (node->ChildNodes[1])
20259 DockNodeFindInfo(node->ChildNodes[1], info);
20264 IM_ASSERT(
id != 0);
20266 if (window->ID == id)
20273static void ImGui::DockNodeUpdateFlagsAndCollapse(
ImGuiDockNode *node)
20276 IM_ASSERT(node->ParentNode == NULL || node->ParentNode->ChildNodes[0] == node ||
20277 node->ParentNode->ChildNodes[1] == node);
20280 if (node->ParentNode)
20281 node->SharedFlags = node->ParentNode->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
20288 node->HasCentralNodeChild =
false;
20289 if (node->ChildNodes[0])
20290 DockNodeUpdateFlagsAndCollapse(node->ChildNodes[0]);
20291 if (node->ChildNodes[1])
20292 DockNodeUpdateFlagsAndCollapse(node->ChildNodes[1]);
20296 node->LocalFlagsInWindows = ImGuiDockNodeFlags_None;
20297 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
20300 IM_ASSERT(window->DockNode == node);
20302 bool node_was_active = (node->LastFrameActive + 1 == g.FrameCount);
20303 bool remove =
false;
20304 remove |= node_was_active && (window->LastFrameActive + 1 < g.FrameCount);
20305 remove |= node_was_active && (node->WantCloseAll || node->WantCloseTabId == window->TabId) &&
20306 window->HasCloseButton &&
20307 !(window->Flags & ImGuiWindowFlags_UnsavedDocument);
20308 remove |= (window->DockTabWantClose);
20311 window->DockTabWantClose =
false;
20312 if (node->Windows.Size == 1 && !node->IsCentralNode())
20314 DockNodeHideHostWindow(node);
20315 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
20316 DockNodeRemoveWindow(node, window, node->ID);
20319 DockNodeRemoveWindow(node, window, node->ID);
20326 node->LocalFlagsInWindows |= window->WindowClass.DockNodeFlagsOverrideSet;
20328 node->UpdateMergedFlags();
20331 ImGuiDockNodeFlags node_flags = node->MergedFlags;
20332 if (node->WantHiddenTabBarUpdate && node->Windows.Size == 1 && (node_flags & ImGuiDockNodeFlags_AutoHideTabBar) &&
20333 !node->IsHiddenTabBar())
20334 node->WantHiddenTabBarToggle =
true;
20335 node->WantHiddenTabBarUpdate =
false;
20338 if (node->WantHiddenTabBarToggle && node->VisibleWindow &&
20339 (node->VisibleWindow->WindowClass.DockNodeFlagsOverrideSet & ImGuiDockNodeFlags_HiddenTabBar))
20340 node->WantHiddenTabBarToggle =
false;
20343 if (node->Windows.Size > 1)
20344 node->SetLocalFlags(node->LocalFlags & ~ImGuiDockNodeFlags_HiddenTabBar);
20345 else if (node->WantHiddenTabBarToggle)
20346 node->SetLocalFlags(node->LocalFlags ^ ImGuiDockNodeFlags_HiddenTabBar);
20347 node->WantHiddenTabBarToggle =
false;
20349 DockNodeUpdateVisibleFlag(node);
20353static void ImGui::DockNodeUpdateHasCentralNodeChild(
ImGuiDockNode *node)
20355 node->HasCentralNodeChild =
false;
20356 if (node->ChildNodes[0])
20357 DockNodeUpdateHasCentralNodeChild(node->ChildNodes[0]);
20358 if (node->ChildNodes[1])
20359 DockNodeUpdateHasCentralNodeChild(node->ChildNodes[1]);
20360 if (node->IsRootNode())
20365 mark_node->HasCentralNodeChild =
true;
20366 mark_node = mark_node->ParentNode;
20371static void ImGui::DockNodeUpdateVisibleFlag(
ImGuiDockNode *node)
20374 bool is_visible = (node->ParentNode == NULL) ? node->IsDockSpace() : node->IsCentralNode();
20375 is_visible |= (node->Windows.Size > 0);
20376 is_visible |= (node->ChildNodes[0] && node->ChildNodes[0]->IsVisible);
20377 is_visible |= (node->ChildNodes[1] && node->ChildNodes[1]->IsVisible);
20378 node->IsVisible = is_visible;
20384 IM_ASSERT(node->WantMouseMove ==
true);
20385 StartMouseMovingWindow(window);
20386 g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - node->Pos;
20387 g.MovingWindow = window;
20389 node->WantMouseMove =
false;
20393static void ImGui::DockNodeUpdateForRootNode(
ImGuiDockNode *node)
20395 DockNodeUpdateFlagsAndCollapse(node);
20402 DockNodeFindInfo(node, &info);
20403 node->CentralNode = info.CentralNode;
20404 node->OnlyNodeWithWindows = (info.CountNodesWithWindows == 1) ? info.FirstNodeWithWindows : NULL;
20405 node->CountNodeWithWindows = info.CountNodesWithWindows;
20406 if (node->LastFocusedNodeId == 0 && info.FirstNodeWithWindows != NULL)
20407 node->LastFocusedNodeId = info.FirstNodeWithWindows->ID;
20413 if (
ImGuiDockNode *first_node_with_windows = info.FirstNodeWithWindows)
20415 node->WindowClass = first_node_with_windows->Windows[0]->WindowClass;
20416 for (
int n = 1; n < first_node_with_windows->Windows.Size; n++)
20417 if (first_node_with_windows->Windows[n]->WindowClass.DockingAllowUnclassed ==
false)
20419 node->WindowClass = first_node_with_windows->Windows[n]->WindowClass;
20427 mark_node->HasCentralNodeChild =
true;
20428 mark_node = mark_node->ParentNode;
20439 if (node->HostWindow && node->HostWindow != host_window && node->HostWindow->DockNodeAsHost == node)
20440 node->HostWindow->DockNodeAsHost = NULL;
20442 host_window->DockNodeAsHost = node;
20443 node->HostWindow = host_window;
20449 IM_ASSERT(node->LastFrameActive != g.FrameCount);
20450 node->LastFrameAlive = g.FrameCount;
20451 node->IsBgDrawnThisFrame =
false;
20453 node->CentralNode = node->OnlyNodeWithWindows = NULL;
20454 if (node->IsRootNode())
20455 DockNodeUpdateForRootNode(node);
20458 if (node->TabBar && node->IsNoTabBar())
20459 DockNodeRemoveTabBar(node);
20463 bool want_to_hide_host_window =
false;
20464 if (node->IsFloatingNode())
20466 if (node->Windows.Size <= 1 && node->IsLeafNode())
20467 if (!g.IO.ConfigDockingAlwaysTabBar &&
20468 (node->Windows.Size == 0 || !node->Windows[0]->WindowClass.DockingAlwaysTabBar))
20469 want_to_hide_host_window =
true;
20470 if (node->CountNodeWithWindows == 0)
20471 want_to_hide_host_window =
true;
20473 if (want_to_hide_host_window)
20475 if (node->Windows.Size == 1)
20479 node->Pos = single_window->Pos;
20480 node->Size = single_window->SizeFull;
20481 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Window;
20484 if (node->HostWindow && g.NavWindow == node->HostWindow)
20485 FocusWindow(single_window);
20486 if (node->HostWindow)
20488 IMGUI_DEBUG_LOG_VIEWPORT(
"[viewport] Node %08X transfer Viewport %08X->%08X to Window '%s'\n", node->ID,
20489 node->HostWindow->Viewport->ID, single_window->ID, single_window->Name);
20490 single_window->Viewport = node->HostWindow->Viewport;
20491 single_window->ViewportId = node->HostWindow->ViewportId;
20492 if (node->HostWindow->ViewportOwned)
20494 single_window->Viewport->ID = single_window->ID;
20495 single_window->Viewport->Window = single_window;
20496 single_window->ViewportOwned =
true;
20499 node->RefViewportId = single_window->ViewportId;
20502 DockNodeHideHostWindow(node);
20503 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
20504 node->WantCloseAll =
false;
20505 node->WantCloseTabId = 0;
20506 node->HasCloseButton = node->HasWindowMenuButton =
false;
20507 node->LastFrameActive = g.FrameCount;
20509 if (node->WantMouseMove && node->Windows.Size == 1)
20510 DockNodeStartMouseMovingWindow(node, node->Windows[0]);
20525 if (node->IsVisible && node->HostWindow == NULL && node->IsFloatingNode() && node->IsLeafNode())
20527 IM_ASSERT(node->Windows.Size > 0);
20529 if (node->SelectedTabId !=
20531 ref_window = DockNodeFindWindowByID(node, node->SelectedTabId);
20532 if (ref_window == NULL)
20533 ref_window = node->Windows[0];
20534 if (ref_window->AutoFitFramesX > 0 || ref_window->AutoFitFramesY > 0)
20536 node->State = ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing;
20541 const ImGuiDockNodeFlags node_flags = node->MergedFlags;
20544 node->HasWindowMenuButton = (node->Windows.Size > 0) && (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0;
20545 node->HasCloseButton =
false;
20550 node->HasCloseButton |= window->HasCloseButton;
20551 window->DockIsActive = (node->Windows.Size > 1);
20553 if (node_flags & ImGuiDockNodeFlags_NoCloseButton)
20554 node->HasCloseButton =
false;
20558 bool beginned_into_host_window =
false;
20559 if (node->IsDockSpace())
20562 IM_ASSERT(node->HostWindow);
20563 host_window = node->HostWindow;
20568 if (node->IsRootNode() && node->IsVisible)
20570 ImGuiWindow *ref_window = (node->Windows.Size > 0) ? node->Windows[0] : NULL;
20573 if (node->AuthorityForPos == ImGuiDataAuthority_Window && ref_window)
20574 SetNextWindowPos(ref_window->Pos);
20575 else if (node->AuthorityForPos == ImGuiDataAuthority_DockNode)
20576 SetNextWindowPos(node->Pos);
20579 if (node->AuthorityForSize == ImGuiDataAuthority_Window && ref_window)
20580 SetNextWindowSize(ref_window->SizeFull);
20581 else if (node->AuthorityForSize == ImGuiDataAuthority_DockNode)
20582 SetNextWindowSize(node->Size);
20585 if (node->AuthorityForSize == ImGuiDataAuthority_Window && ref_window)
20586 SetNextWindowCollapsed(ref_window->Collapsed);
20589 if (node->AuthorityForViewport == ImGuiDataAuthority_Window && ref_window)
20590 SetNextWindowViewport(ref_window->ViewportId);
20591 else if (node->AuthorityForViewport == ImGuiDataAuthority_Window && node->RefViewportId != 0)
20592 SetNextWindowViewport(node->RefViewportId);
20594 SetNextWindowClass(&node->WindowClass);
20597 char window_label[20];
20598 DockNodeGetHostWindowTitle(node, window_label, IM_ARRAYSIZE(window_label));
20599 ImGuiWindowFlags window_flags =
20600 ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_DockNodeHost;
20601 window_flags |= ImGuiWindowFlags_NoFocusOnAppearing;
20603 ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoCollapse;
20604 window_flags |= ImGuiWindowFlags_NoTitleBar;
20606 SetNextWindowBgAlpha(0.0f);
20607 PushStyleVar(ImGuiStyleVar_WindowPadding,
ImVec2(0, 0));
20608 Begin(window_label, NULL, window_flags);
20610 beginned_into_host_window =
true;
20612 host_window = g.CurrentWindow;
20613 DockNodeSetupHostWindow(node, host_window);
20614 host_window->DC.CursorPos = host_window->Pos;
20615 node->Pos = host_window->Pos;
20616 node->Size = host_window->Size;
20625 if (node->HostWindow->Appearing)
20626 BringWindowToDisplayFront(node->HostWindow);
20628 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Auto;
20630 else if (node->ParentNode)
20632 node->HostWindow = host_window = node->ParentNode->HostWindow;
20633 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Auto;
20635 if (node->WantMouseMove && node->HostWindow)
20636 DockNodeStartMouseMovingWindow(node, node->HostWindow);
20638 node->RefViewportId = 0;
20641 if (node->IsSplitNode())
20642 IM_ASSERT(node->TabBar == NULL);
20643 if (node->IsRootNode())
20644 if (
ImGuiWindow *p_window = g.NavWindow ? g.NavWindow->RootWindow : NULL)
20645 while (p_window != NULL && p_window->DockNode != NULL)
20647 ImGuiDockNode *p_node = DockNodeGetRootNode(p_window->DockNode);
20648 if (p_node == node)
20650 node->LastFocusedNodeId = p_window->DockNode->ID;
20653 p_window = p_node->HostWindow ? p_node->HostWindow->RootWindow : NULL;
20659 const bool central_node_hole = node->IsRootNode() && host_window &&
20660 (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0 && central_node != NULL &&
20661 central_node->IsEmpty();
20662 bool central_node_hole_register_hit_test_hole = central_node_hole;
20663 if (central_node_hole)
20664 if (
const ImGuiPayload *payload = ImGui::GetDragDropPayload())
20665 if (payload->IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) &&
20666 DockNodeIsDropAllowed(host_window, *(
ImGuiWindow **)payload->Data))
20667 central_node_hole_register_hit_test_hole =
false;
20668 if (central_node_hole_register_hit_test_hole)
20673 IM_ASSERT(node->IsDockSpace());
20675 ImGuiDockNode *root_node = DockNodeGetRootNode(central_node);
20676 ImRect root_rect(root_node->Pos, root_node->Pos + root_node->Size);
20677 ImRect hole_rect(central_node->Pos, central_node->Pos + central_node->Size);
20678 if (hole_rect.Min.x > root_rect.Min.x)
20680 hole_rect.Min.x += g.WindowsBorderHoverPadding;
20682 if (hole_rect.Max.x < root_rect.Max.x)
20684 hole_rect.Max.x -= g.WindowsBorderHoverPadding;
20686 if (hole_rect.Min.y > root_rect.Min.y)
20688 hole_rect.Min.y += g.WindowsBorderHoverPadding;
20690 if (hole_rect.Max.y < root_rect.Max.y)
20692 hole_rect.Max.y -= g.WindowsBorderHoverPadding;
20695 if (central_node_hole && !hole_rect.IsInverted())
20697 SetWindowHitTestHole(host_window, hole_rect.Min, hole_rect.Max - hole_rect.Min);
20698 if (host_window->ParentWindow)
20699 SetWindowHitTestHole(host_window->ParentWindow, hole_rect.Min, hole_rect.Max - hole_rect.Min);
20704 if (node->IsRootNode() && host_window)
20706 DockNodeTreeUpdatePosSize(node, host_window->Pos, host_window->Size);
20707 PushStyleColor(ImGuiCol_Separator, g.Style.Colors[ImGuiCol_Border]);
20708 PushStyleColor(ImGuiCol_SeparatorActive, g.Style.Colors[ImGuiCol_ResizeGripActive]);
20709 PushStyleColor(ImGuiCol_SeparatorHovered, g.Style.Colors[ImGuiCol_ResizeGripHovered]);
20710 DockNodeTreeUpdateSplitter(node);
20715 if (host_window && node->IsEmpty() && node->IsVisible)
20717 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
20718 node->LastBgColor =
20719 (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) ? 0 : GetColorU32(ImGuiCol_DockingEmptyBg);
20720 if (node->LastBgColor != 0)
20721 host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, node->LastBgColor);
20722 node->IsBgDrawnThisFrame =
true;
20729 const bool render_dockspace_bg =
20730 node->IsRootNode() && host_window && (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0;
20731 if (render_dockspace_bg && node->IsVisible)
20733 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
20734 if (central_node_hole)
20735 RenderRectFilledWithHole(host_window->DrawList, node->Rect(), central_node->Rect(),
20736 GetColorU32(ImGuiCol_WindowBg), 0.0f);
20738 host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, GetColorU32(ImGuiCol_WindowBg),
20744 host_window->DrawList->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
20745 if (host_window && node->Windows.Size > 0)
20747 DockNodeUpdateTabBar(node, host_window);
20751 node->WantCloseAll =
false;
20752 node->WantCloseTabId = 0;
20753 node->IsFocused =
false;
20755 if (node->TabBar && node->TabBar->SelectedTabId)
20756 node->SelectedTabId = node->TabBar->SelectedTabId;
20757 else if (node->Windows.Size > 0)
20758 node->SelectedTabId = node->Windows[0]->TabId;
20761 if (host_window && node->IsVisible)
20762 if (node->IsRootNode() && (g.MovingWindow == NULL || g.MovingWindow->RootWindowDockTree != host_window))
20763 BeginDockableDragDropTarget(host_window);
20766 node->LastFrameActive = g.FrameCount;
20772 if (node->ChildNodes[0])
20773 DockNodeUpdate(node->ChildNodes[0]);
20774 if (node->ChildNodes[1])
20775 DockNodeUpdate(node->ChildNodes[1]);
20778 if (node->IsRootNode())
20779 RenderWindowOuterBorders(host_window);
20783 if (beginned_into_host_window)
20789static int IMGUI_CDECL TabItemComparerByDockOrder(
const void *lhs,
const void *rhs)
20793 if (
int d = ((a->DockOrder == -1) ? INT_MAX : a->DockOrder) - ((b->DockOrder == -1) ? INT_MAX : b->DockOrder))
20795 return (a->BeginOrderWithinContext - b->BeginOrderWithinContext);
20807 if (tab_bar->Tabs.Size == 1)
20810 if (MenuItem(LocalizeGetMsg(ImGuiLocKey_DockingHideTabBar), NULL, node->IsHiddenTabBar()))
20811 node->WantHiddenTabBarToggle =
true;
20816 for (
int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
20819 if (tab->Flags & ImGuiTabItemFlags_Button)
20821 if (Selectable(TabBarGetTabName(tab_bar, tab), tab->ID == tab_bar->SelectedTabId))
20822 TabBarQueueFocus(tab_bar, tab);
20833 if (g.Style.WindowMenuButtonPosition == ImGuiDir_Left)
20834 SetNextWindowPos(
ImVec2(node->Pos.x, node->Pos.y + GetFrameHeight()), ImGuiCond_Always,
ImVec2(0.0f, 0.0f));
20836 SetNextWindowPos(
ImVec2(node->Pos.x + node->Size.x, node->Pos.y + GetFrameHeight()), ImGuiCond_Always,
20838 if (BeginPopup(
"#WindowMenu"))
20840 node->IsFocused =
true;
20841 g.DockNodeWindowMenuHandler(&g, node, tab_bar);
20849 if (node->TabBar == NULL || node->HostWindow == NULL)
20851 if (node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly)
20853 if (node->TabBar->ID == 0)
20855 Begin(node->HostWindow->Name);
20856 PushOverrideID(node->ID);
20857 bool ret = BeginTabBarEx(node->TabBar, node->TabBar->BarRect, node->TabBar->Flags);
20863void ImGui::DockNodeEndAmendTabBar()
20874 if (g.NavWindowingTarget)
20875 return (g.NavWindowingTarget->DockNode == node);
20878 if (g.NavWindow && root_node->LastFocusedNodeId == node->ID)
20882 ImGuiWindow *parent_window = g.NavWindow->RootWindow;
20883 while (parent_window->Flags & ImGuiWindowFlags_ChildMenu)
20884 parent_window = parent_window->ParentWindow->RootWindow;
20886 parent_window->DockNodeAsHost ? parent_window->DockNodeAsHost : parent_window->DockNode;
20887 for (
ImGuiDockNode *parent_node = start_parent_node; parent_node != NULL;
20888 parent_node = parent_node->HostWindow ? parent_node->HostWindow->RootWindow->DockNode : NULL)
20889 if ((parent_node = ImGui::DockNodeGetRootNode(parent_node)) == root_node)
20901 const bool node_was_active = (node->LastFrameActive + 1 == g.FrameCount);
20902 const bool closed_all = node->WantCloseAll && node_was_active;
20903 const ImGuiID closed_one = node->WantCloseTabId && node_was_active;
20904 node->WantCloseAll =
false;
20905 node->WantCloseTabId = 0;
20908 bool is_focused =
false;
20910 if (IsDockNodeTitleBarHighlighted(node, root_node))
20914 if (node->IsHiddenTabBar() || node->IsNoTabBar())
20916 node->VisibleWindow = (node->Windows.Size > 0) ? node->Windows[0] : NULL;
20917 node->IsFocused = is_focused;
20919 node->LastFrameFocused = g.FrameCount;
20920 if (node->VisibleWindow)
20923 if (is_focused || root_node->VisibleWindow == NULL)
20924 root_node->VisibleWindow = node->VisibleWindow;
20926 node->TabBar->VisibleTabId = node->VisibleWindow->TabId;
20933 bool backup_skip_item = host_window->SkipItems;
20934 if (!node->IsDockSpace())
20936 host_window->SkipItems =
false;
20937 host_window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
20943 PushOverrideID(node->ID);
20945 bool tab_bar_is_recreated = (tab_bar == NULL);
20946 if (tab_bar == NULL)
20948 DockNodeAddTabBar(node);
20949 tab_bar = node->TabBar;
20952 ImGuiID focus_tab_id = 0;
20953 node->IsFocused = is_focused;
20955 const ImGuiDockNodeFlags node_flags = node->MergedFlags;
20956 const bool has_window_menu_button =
20957 (node_flags & ImGuiDockNodeFlags_NoWindowMenuButton) == 0 && (style.WindowMenuButtonPosition != ImGuiDir_None);
20961 if (has_window_menu_button && IsPopupOpen(
"#WindowMenu"))
20963 ImGuiID next_selected_tab_id = tab_bar->NextSelectedTabId;
20964 DockNodeWindowMenuUpdate(node, tab_bar);
20965 if (tab_bar->NextSelectedTabId != 0 && tab_bar->NextSelectedTabId != next_selected_tab_id)
20966 focus_tab_id = tab_bar->NextSelectedTabId;
20967 is_focused |= node->IsFocused;
20971 ImRect title_bar_rect, tab_bar_rect;
20972 ImVec2 window_menu_button_pos;
20973 ImVec2 close_button_pos;
20974 DockNodeCalcTabBarLayout(node, &title_bar_rect, &tab_bar_rect, &window_menu_button_pos, &close_button_pos);
20977 const int tabs_count_old = tab_bar->Tabs.Size;
20978 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
20981 if (TabBarFindTabByID(tab_bar, window->TabId) == NULL)
20982 TabBarAddTab(tab_bar, ImGuiTabItemFlags_Unsorted, window);
20987 node->LastFrameFocused = g.FrameCount;
20988 ImU32 title_bar_col = GetColorU32(host_window->Collapsed ? ImGuiCol_TitleBgCollapsed
20989 : is_focused ? ImGuiCol_TitleBgActive
20990 : ImGuiCol_TitleBg);
20991 ImDrawFlags rounding_flags =
20992 CalcRoundingFlagsForRectInRect(title_bar_rect, host_window->Rect(), g.Style.DockingSeparatorSize);
20993 host_window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col,
20994 host_window->WindowRounding, rounding_flags);
20997 if (has_window_menu_button)
20999 if (CollapseButton(host_window->GetID(
"#COLLAPSE"), window_menu_button_pos,
21001 OpenPopup(
"#WindowMenu");
21002 if (IsItemActive())
21003 focus_tab_id = tab_bar->SelectedTabId;
21004 if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal) && g.HoveredIdTimer > 0.5f)
21005 SetTooltip(
"%s", LocalizeGetMsg(ImGuiLocKey_DockingDragToUndockOrMoveNode));
21009 int tabs_unsorted_start = tab_bar->Tabs.Size;
21010 for (
int tab_n = tab_bar->Tabs.Size - 1; tab_n >= 0 && (tab_bar->Tabs[tab_n].Flags & ImGuiTabItemFlags_Unsorted);
21015 tab_bar->Tabs[tab_n].Flags &= ~ImGuiTabItemFlags_Unsorted;
21016 tabs_unsorted_start = tab_n;
21018 if (tab_bar->Tabs.Size > tabs_unsorted_start)
21020 IMGUI_DEBUG_LOG_DOCKING(
"[docking] In node 0x%08X: %d new appearing tabs:%s\n", node->ID,
21021 tab_bar->Tabs.Size - tabs_unsorted_start,
21022 (tab_bar->Tabs.Size > tabs_unsorted_start + 1) ?
" (will sort)" :
"");
21023 for (
int tab_n = tabs_unsorted_start; tab_n < tab_bar->Tabs.Size; tab_n++)
21027 IMGUI_DEBUG_LOG_DOCKING(
"[docking] - Tab 0x%08X '%s' Order %d\n", tab->ID, TabBarGetTabName(tab_bar, tab),
21028 tab->Window ? tab->Window->DockOrder : -1);
21030 IMGUI_DEBUG_LOG_DOCKING(
"[docking] SelectedTabId = 0x%08X, NavWindow->TabId = 0x%08X\n", node->SelectedTabId,
21031 g.NavWindow ? g.NavWindow->TabId : -1);
21032 if (tab_bar->Tabs.Size > tabs_unsorted_start + 1)
21033 ImQsort(tab_bar->Tabs.Data + tabs_unsorted_start, tab_bar->Tabs.Size - tabs_unsorted_start,
21038 if (g.NavWindow && g.NavWindow->RootWindow->DockNode == node)
21039 tab_bar->SelectedTabId = g.NavWindow->RootWindow->TabId;
21042 if (tab_bar_is_recreated && TabBarFindTabByID(tab_bar, node->SelectedTabId) != NULL)
21043 tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = node->SelectedTabId;
21044 else if (tab_bar->Tabs.Size > tabs_count_old)
21045 tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = tab_bar->Tabs.back().Window->TabId;
21048 ImGuiTabBarFlags tab_bar_flags =
21049 ImGuiTabBarFlags_Reorderable |
21050 ImGuiTabBarFlags_AutoSelectNewTabs;
21052 ImGuiTabBarFlags_SaveSettings | ImGuiTabBarFlags_DockNode;
21053 tab_bar_flags |= ImGuiTabBarFlags_DrawSelectedOverline;
21054 if (!host_window->Collapsed && is_focused)
21055 tab_bar_flags |= ImGuiTabBarFlags_IsFocused;
21056 tab_bar->ID = GetID(
"#TabBar");
21057 tab_bar->SeparatorMinX = node->Pos.x + host_window->WindowBorderSize;
21058 tab_bar->SeparatorMaxX = node->Pos.x + node->Size.x - host_window->WindowBorderSize;
21059 BeginTabBarEx(tab_bar, tab_bar_rect, tab_bar_flags);
21063 ImVec4 backup_style_cols[ImGuiWindowDockStyleCol_COUNT];
21064 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
21065 backup_style_cols[color_n] = g.Style.Colors[GWindowDockStyleColors[color_n]];
21068 node->VisibleWindow = NULL;
21069 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
21072 if ((closed_all || closed_one == window->TabId) && window->HasCloseButton &&
21073 !(window->Flags & ImGuiWindowFlags_UnsavedDocument))
21075 if (window->LastFrameActive + 1 >= g.FrameCount || !node_was_active)
21077 ImGuiTabItemFlags tab_item_flags = 0;
21078 tab_item_flags |= window->WindowClass.TabItemFlagsOverrideSet;
21079 if (window->Flags & ImGuiWindowFlags_UnsavedDocument)
21080 tab_item_flags |= ImGuiTabItemFlags_UnsavedDocument;
21081 if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
21082 tab_item_flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
21085 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
21086 g.Style.Colors[GWindowDockStyleColors[color_n]] =
21087 ColorConvertU32ToFloat4(window->DockStyle.Colors[color_n]);
21091 bool tab_open =
true;
21092 TabItemEx(tab_bar, window->Name, window->HasCloseButton ? &tab_open : NULL, tab_item_flags, window);
21094 node->WantCloseTabId = window->TabId;
21095 if (tab_bar->VisibleTabId == window->TabId)
21096 node->VisibleWindow = window;
21099 window->DC.DockTabItemStatusFlags = g.LastItemData.StatusFlags;
21100 window->DC.DockTabItemRect = g.LastItemData.Rect;
21103 if (g.NavWindow && g.NavWindow->RootWindow == window &&
21104 (window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0)
21105 host_window->NavLastIds[1] = window->TabId;
21110 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
21111 g.Style.Colors[GWindowDockStyleColors[color_n]] = backup_style_cols[color_n];
21114 if (node->VisibleWindow)
21115 if (is_focused || root_node->VisibleWindow == NULL)
21116 root_node->VisibleWindow = node->VisibleWindow;
21121 const bool close_button_is_enabled =
21122 node->HasCloseButton && node->VisibleWindow && node->VisibleWindow->HasCloseButton;
21123 const bool close_button_is_visible = node->HasCloseButton;
21126 if (close_button_is_visible)
21128 if (!close_button_is_enabled)
21130 PushItemFlag(ImGuiItemFlags_Disabled,
true);
21131 PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_Text] *
ImVec4(1.0f, 1.0f, 1.0f, 0.4f));
21133 if (CloseButton(host_window->GetID(
"#CLOSE"), close_button_pos))
21135 node->WantCloseAll =
true;
21136 for (
int n = 0; n < tab_bar->Tabs.Size; n++)
21137 TabBarCloseTab(tab_bar, &tab_bar->Tabs[n]);
21141 if (!close_button_is_enabled)
21151 ImGuiID title_bar_id = host_window->GetID(
"#TITLEBAR");
21152 if (g.HoveredId == 0 || g.HoveredId == title_bar_id || g.ActiveId == title_bar_id)
21157 KeepAliveID(title_bar_id);
21158 ButtonBehavior(title_bar_rect, title_bar_id, NULL, &held, ImGuiButtonFlags_AllowOverlap);
21159 if (g.HoveredId == title_bar_id)
21161 g.LastItemData.ID = title_bar_id;
21165 if (IsMouseClicked(0))
21166 focus_tab_id = tab_bar->SelectedTabId;
21169 if (
ImGuiTabItem *tab = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
21170 StartMouseMovingWindowOrNode(tab->Window ? tab->Window : node->HostWindow, node,
21181 if (tab_bar->NextSelectedTabId)
21182 focus_tab_id = tab_bar->NextSelectedTabId;
21185 if (focus_tab_id != 0)
21186 if (
ImGuiTabItem *tab = TabBarFindTabByID(tab_bar, focus_tab_id))
21189 FocusWindow(tab->Window);
21190 NavInitWindow(tab->Window,
false);
21197 if (!node->IsDockSpace())
21199 host_window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
21200 host_window->SkipItems = backup_skip_item;
21206 IM_ASSERT(node->TabBar == NULL);
21210static void ImGui::DockNodeRemoveTabBar(
ImGuiDockNode *node)
21212 if (node->TabBar == NULL)
21214 IM_DELETE(node->TabBar);
21215 node->TabBar = NULL;
21220 if (host_window->DockNodeAsHost && host_window->DockNodeAsHost->IsDockSpace() &&
21221 payload->BeginOrderWithinContext < host_window->BeginOrderWithinContext)
21225 host_window->DockNodeAsHost ? &host_window->DockNodeAsHost->WindowClass : &host_window->WindowClass;
21227 if (host_class->ClassId != payload_class->ClassId)
21230 if (host_class->ClassId != 0 && host_class->DockingAllowUnclassed && payload_class->ClassId == 0)
21232 if (payload_class->ClassId != 0 && payload_class->DockingAllowUnclassed && host_class->ClassId == 0)
21244 for (
int i = g.OpenPopupStack.Size - 1; i >= 0; i--)
21245 if (
ImGuiWindow *popup_window = g.OpenPopupStack[i].Window)
21246 if (ImGui::IsWindowWithinBeginStackOf(payload,
21255 if (root_payload->DockNodeAsHost && root_payload->DockNodeAsHost->IsSplitNode())
21258 const int payload_count = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->Windows.Size : 1;
21259 for (
int payload_n = 0; payload_n < payload_count; payload_n++)
21262 root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->Windows[payload_n] : root_payload;
21263 if (DockNodeIsDropAllowedOne(payload, host_window))
21271static void ImGui::DockNodeCalcTabBarLayout(
const ImGuiDockNode *node,
ImRect *out_title_rect,
ImRect *out_tab_bar_rect,
21272 ImVec2 *out_window_menu_button_pos,
ImVec2 *out_close_button_pos)
21277 ImRect r =
ImRect(node->Pos.x, node->Pos.y, node->Pos.x + node->Size.x,
21278 node->Pos.y + g.FontSize + g.Style.FramePadding.y * 2.0f);
21279 if (out_title_rect)
21281 *out_title_rect = r;
21284 r.Min.x += style.WindowBorderSize;
21285 r.Max.x -= style.WindowBorderSize;
21287 float button_sz = g.FontSize;
21288 r.Min.x += style.FramePadding.x;
21289 r.Max.x -= style.FramePadding.x;
21290 ImVec2 window_menu_button_pos =
ImVec2(r.Min.x, r.Min.y + style.FramePadding.y);
21291 if (node->HasCloseButton)
21293 if (out_close_button_pos)
21294 *out_close_button_pos =
ImVec2(r.Max.x - button_sz, r.Min.y + style.FramePadding.y);
21295 r.Max.x -= button_sz + style.ItemInnerSpacing.x;
21297 if (node->HasWindowMenuButton && style.WindowMenuButtonPosition == ImGuiDir_Left)
21299 r.Min.x += button_sz + style.ItemInnerSpacing.x;
21301 else if (node->HasWindowMenuButton && style.WindowMenuButtonPosition == ImGuiDir_Right)
21303 window_menu_button_pos =
ImVec2(r.Max.x - button_sz, r.Min.y + style.FramePadding.y);
21304 r.Max.x -= button_sz + style.ItemInnerSpacing.x;
21306 if (out_tab_bar_rect)
21308 *out_tab_bar_rect = r;
21310 if (out_window_menu_button_pos)
21312 *out_window_menu_button_pos = window_menu_button_pos;
21316void ImGui::DockNodeCalcSplitRects(
ImVec2 &pos_old,
ImVec2 &size_old,
ImVec2 &pos_new,
ImVec2 &size_new, ImGuiDir dir,
21317 ImVec2 size_new_desired)
21320 const float dock_spacing = g.Style.ItemInnerSpacing.x;
21321 const ImGuiAxis axis = (dir == ImGuiDir_Left || dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
21322 pos_new[axis ^ 1] = pos_old[axis ^ 1];
21323 size_new[axis ^ 1] = size_old[axis ^ 1];
21326 const float w_avail = size_old[axis] - dock_spacing;
21327 if (size_new_desired[axis] > 0.0f && size_new_desired[axis] <= w_avail * 0.5f)
21329 size_new[axis] = size_new_desired[axis];
21330 size_old[axis] = IM_TRUNC(w_avail - size_new[axis]);
21334 size_new[axis] = IM_TRUNC(w_avail * 0.5f);
21335 size_old[axis] = IM_TRUNC(w_avail - size_new[axis]);
21339 if (dir == ImGuiDir_Right || dir == ImGuiDir_Down)
21341 pos_new[axis] = pos_old[axis] + size_old[axis] + dock_spacing;
21343 else if (dir == ImGuiDir_Left || dir == ImGuiDir_Up)
21345 pos_new[axis] = pos_old[axis];
21346 pos_old[axis] = pos_new[axis] + size_new[axis] + dock_spacing;
21351bool ImGui::DockNodeCalcDropRectsAndTestMousePos(
const ImRect &parent, ImGuiDir dir,
ImRect &out_r,
bool outer_docking,
21356 const float parent_smaller_axis = ImMin(parent.GetWidth(), parent.GetHeight());
21357 const float hs_for_central_nodes = ImMin(g.FontSize * 1.5f, ImMax(g.FontSize * 0.5f, parent_smaller_axis / 8.0f));
21367 hs_w = ImTrunc(hs_for_central_nodes * 1.50f);
21368 hs_h = ImTrunc(hs_for_central_nodes * 0.80f);
21369 off = ImTrunc(
ImVec2(parent.GetWidth() * 0.5f - hs_h, parent.GetHeight() * 0.5f - hs_h));
21373 hs_w = ImTrunc(hs_for_central_nodes);
21374 hs_h = ImTrunc(hs_for_central_nodes * 0.90f);
21375 off = ImTrunc(
ImVec2(hs_w * 2.40f, hs_w * 2.40f));
21378 ImVec2 c = ImTrunc(parent.GetCenter());
21379 if (dir == ImGuiDir_None)
21381 out_r =
ImRect(c.x - hs_w, c.y - hs_w, c.x + hs_w, c.y + hs_w);
21383 else if (dir == ImGuiDir_Up)
21385 out_r =
ImRect(c.x - hs_w, c.y - off.y - hs_h, c.x + hs_w, c.y - off.y + hs_h);
21387 else if (dir == ImGuiDir_Down)
21389 out_r =
ImRect(c.x - hs_w, c.y + off.y - hs_h, c.x + hs_w, c.y + off.y + hs_h);
21391 else if (dir == ImGuiDir_Left)
21393 out_r =
ImRect(c.x - off.x - hs_h, c.y - hs_w, c.x - off.x + hs_h, c.y + hs_w);
21395 else if (dir == ImGuiDir_Right)
21397 out_r =
ImRect(c.x + off.x - hs_h, c.y - hs_w, c.x + off.x + hs_h, c.y + hs_w);
21400 if (test_mouse_pos == NULL)
21404 if (!outer_docking)
21408 hit_r.Expand(ImTrunc(hs_w * 0.30f));
21409 ImVec2 mouse_delta = (*test_mouse_pos - c);
21410 float mouse_delta_len2 = ImLengthSqr(mouse_delta);
21411 float r_threshold_center = hs_w * 1.4f;
21412 float r_threshold_sides = hs_w * (1.4f + 1.2f);
21413 if (mouse_delta_len2 < r_threshold_center * r_threshold_center)
21414 return (dir == ImGuiDir_None);
21415 if (mouse_delta_len2 < r_threshold_sides * r_threshold_sides)
21416 return (dir == ImGetDirQuadrantFromDelta(mouse_delta.x, mouse_delta.y));
21418 return hit_r.Contains(*test_mouse_pos);
21432 if (payload_node == NULL)
21433 payload_node = payload_window->DockNodeAsHost;
21435 (host_node && !host_node->IsVisible) ? DockNodeGetRootNode(host_node) : host_node;
21436 if (ref_node_for_rect)
21437 IM_ASSERT(ref_node_for_rect->IsVisible ==
true);
21440 ImGuiDockNodeFlags src_node_flags =
21441 payload_node ? payload_node->MergedFlags : payload_window->WindowClass.DockNodeFlagsOverrideSet;
21442 ImGuiDockNodeFlags dst_node_flags =
21443 host_node ? host_node->MergedFlags : host_window->WindowClass.DockNodeFlagsOverrideSet;
21444 data->IsCenterAvailable =
true;
21445 if (is_outer_docking)
21446 data->IsCenterAvailable =
false;
21447 else if (dst_node_flags & ImGuiDockNodeFlags_NoDockingOverMe)
21448 data->IsCenterAvailable =
false;
21449 else if (host_node && (dst_node_flags & ImGuiDockNodeFlags_NoDockingOverCentralNode) && host_node->IsCentralNode())
21450 data->IsCenterAvailable =
false;
21451 else if ((!host_node || !host_node->IsEmpty()) && payload_node && payload_node->IsSplitNode() &&
21452 (payload_node->OnlyNodeWithWindows == NULL))
21453 data->IsCenterAvailable =
false;
21454 else if ((src_node_flags & ImGuiDockNodeFlags_NoDockingOverOther) && (!host_node || !host_node->IsEmpty()))
21455 data->IsCenterAvailable =
false;
21456 else if ((src_node_flags & ImGuiDockNodeFlags_NoDockingOverEmpty) && host_node && host_node->IsEmpty())
21457 data->IsCenterAvailable =
false;
21459 data->IsSidesAvailable =
true;
21460 if ((dst_node_flags & ImGuiDockNodeFlags_NoDockingSplit) || g.IO.ConfigDockingNoSplit)
21461 data->IsSidesAvailable =
false;
21462 else if (!is_outer_docking && host_node && host_node->ParentNode == NULL && host_node->IsCentralNode())
21463 data->IsSidesAvailable =
false;
21464 else if (src_node_flags & ImGuiDockNodeFlags_NoDockingSplitOther)
21465 data->IsSidesAvailable =
false;
21469 data->FutureNode.HasCloseButton =
21470 (host_node ? host_node->HasCloseButton : host_window->HasCloseButton) || (payload_window->HasCloseButton);
21471 data->FutureNode.HasWindowMenuButton = host_node ? true : ((host_window->Flags & ImGuiWindowFlags_NoCollapse) == 0);
21472 data->FutureNode.Pos = ref_node_for_rect ? ref_node_for_rect->Pos : host_window->Pos;
21473 data->FutureNode.Size = ref_node_for_rect ? ref_node_for_rect->Size : host_window->Size;
21476 IM_ASSERT(ImGuiDir_None == -1);
21477 data->SplitNode = host_node;
21478 data->SplitDir = ImGuiDir_None;
21479 data->IsSplitDirExplicit =
false;
21480 if (!host_window->Collapsed)
21481 for (
int dir = ImGuiDir_None; dir < ImGuiDir_COUNT; dir++)
21483 if (dir == ImGuiDir_None && !data->IsCenterAvailable)
21485 if (dir != ImGuiDir_None && !data->IsSidesAvailable)
21487 if (DockNodeCalcDropRectsAndTestMousePos(data->FutureNode.Rect(), (ImGuiDir)dir,
21488 data->DropRectsDraw[dir + 1], is_outer_docking, &g.IO.MousePos))
21490 data->SplitDir = (ImGuiDir)dir;
21491 data->IsSplitDirExplicit =
true;
21497 data->IsDropAllowed = (data->SplitDir != ImGuiDir_None) || (data->IsCenterAvailable);
21498 if (!is_explicit_target && !data->IsSplitDirExplicit && !g.IO.ConfigDockingWithShift)
21499 data->IsDropAllowed =
false;
21502 data->SplitRatio = 0.0f;
21503 if (data->SplitDir != ImGuiDir_None)
21505 ImGuiDir split_dir = data->SplitDir;
21506 ImGuiAxis split_axis = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
21507 ImVec2 pos_new, pos_old = data->FutureNode.Pos;
21508 ImVec2 size_new, size_old = data->FutureNode.Size;
21509 DockNodeCalcSplitRects(pos_old, size_old, pos_new, size_new, split_dir, payload_window->Size);
21512 float split_ratio = ImSaturate(size_new[split_axis] / data->FutureNode.Size[split_axis]);
21513 data->FutureNode.Pos = pos_new;
21514 data->FutureNode.Size = size_new;
21516 (split_dir == ImGuiDir_Right || split_dir == ImGuiDir_Down) ? (1.0f - split_ratio) : (split_ratio);
21524 IM_ASSERT(g.CurrentWindow == host_window);
21529 const bool is_transparent_payload = g.IO.ConfigDockingTransparentPayload;
21532 int overlay_draw_lists_count = 0;
21534 overlay_draw_lists[overlay_draw_lists_count++] = GetForegroundDrawList(host_window->Viewport);
21535 if (host_window->Viewport != root_payload->Viewport && !is_transparent_payload)
21536 overlay_draw_lists[overlay_draw_lists_count++] = GetForegroundDrawList(root_payload->Viewport);
21539 const ImU32 overlay_col_main = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 0.60f : 0.40f);
21540 const ImU32 overlay_col_drop = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 0.90f : 0.70f);
21541 const ImU32 overlay_col_drop_hovered = GetColorU32(ImGuiCol_DockingPreview, is_transparent_payload ? 1.20f : 1.00f);
21542 const ImU32 overlay_col_lines = GetColorU32(ImGuiCol_NavWindowingHighlight, is_transparent_payload ? 0.80f : 0.60f);
21545 const bool can_preview_tabs =
21546 (root_payload->DockNodeAsHost == NULL || root_payload->DockNodeAsHost->Windows.Size > 0);
21547 if (data->IsDropAllowed)
21549 ImRect overlay_rect = data->FutureNode.Rect();
21550 if (data->SplitDir == ImGuiDir_None && can_preview_tabs)
21551 overlay_rect.Min.y += GetFrameHeight();
21552 if (data->SplitDir != ImGuiDir_None || data->IsCenterAvailable)
21553 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
21554 overlay_draw_lists[overlay_n]->AddRectFilled(
21555 overlay_rect.Min, overlay_rect.Max, overlay_col_main, host_window->WindowRounding,
21556 CalcRoundingFlagsForRectInRect(overlay_rect, host_window->Rect(), g.Style.DockingSeparatorSize));
21560 if (data->IsDropAllowed && can_preview_tabs && data->SplitDir == ImGuiDir_None && data->IsCenterAvailable)
21564 DockNodeCalcTabBarLayout(&data->FutureNode, NULL, &tab_bar_rect, NULL, NULL);
21565 ImVec2 tab_pos = tab_bar_rect.Min;
21566 if (host_node && host_node->TabBar)
21568 if (!host_node->IsHiddenTabBar() && !host_node->IsNoTabBar())
21570 host_node->TabBar->WidthAllTabs +
21571 g.Style.ItemInnerSpacing.x;
21574 tab_pos.x += g.Style.ItemInnerSpacing.x + TabItemCalcSize(host_node->Windows[0]).x;
21576 else if (!(host_window->Flags & ImGuiWindowFlags_DockNodeHost))
21579 g.Style.ItemInnerSpacing.x +
21580 TabItemCalcSize(host_window)
21586 if (root_payload->DockNodeAsHost)
21587 IM_ASSERT(root_payload->DockNodeAsHost->Windows.Size <= root_payload->DockNodeAsHost->TabBar->Tabs.Size);
21588 ImGuiTabBar *tab_bar_with_payload = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->TabBar : NULL;
21589 const int payload_count = tab_bar_with_payload ? tab_bar_with_payload->Tabs.Size : 1;
21590 for (
int payload_n = 0; payload_n < payload_count; payload_n++)
21594 tab_bar_with_payload ? tab_bar_with_payload->Tabs[payload_n].Window : root_payload;
21595 if (tab_bar_with_payload && payload_window == NULL)
21597 if (!DockNodeIsDropAllowedOne(payload_window, host_window))
21601 ImVec2 tab_size = TabItemCalcSize(payload_window);
21602 ImRect tab_bb(tab_pos.x, tab_pos.y, tab_pos.x + tab_size.x, tab_pos.y + tab_size.y);
21603 tab_pos.x += tab_size.x + g.Style.ItemInnerSpacing.x;
21604 const ImU32 overlay_col_text = GetColorU32(payload_window->DockStyle.Colors[ImGuiWindowDockStyleCol_Text]);
21605 const ImU32 overlay_col_tabs =
21606 GetColorU32(payload_window->DockStyle.Colors[ImGuiWindowDockStyleCol_TabSelected]);
21607 PushStyleColor(ImGuiCol_Text, overlay_col_text);
21608 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
21610 ImGuiTabItemFlags tab_flags =
21611 (payload_window->Flags & ImGuiWindowFlags_UnsavedDocument) ? ImGuiTabItemFlags_UnsavedDocument : 0;
21612 if (!tab_bar_rect.Contains(tab_bb))
21613 overlay_draw_lists[overlay_n]->PushClipRect(tab_bar_rect.Min, tab_bar_rect.Max);
21614 TabItemBackground(overlay_draw_lists[overlay_n], tab_bb, tab_flags, overlay_col_tabs);
21615 TabItemLabelAndCloseButton(overlay_draw_lists[overlay_n], tab_bb, tab_flags, g.Style.FramePadding,
21616 payload_window->Name, 0, 0,
false, NULL, NULL);
21617 if (!tab_bar_rect.Contains(tab_bb))
21618 overlay_draw_lists[overlay_n]->PopClipRect();
21625 const float overlay_rounding = ImMax(3.0f, g.Style.FrameRounding);
21626 for (
int dir = ImGuiDir_None; dir < ImGuiDir_COUNT; dir++)
21628 if (!data->DropRectsDraw[dir + 1].IsInverted())
21630 ImRect draw_r = data->DropRectsDraw[dir + 1];
21631 ImRect draw_r_in = draw_r;
21632 draw_r_in.Expand(-2.0f);
21633 ImU32 overlay_col = (data->SplitDir == (ImGuiDir)dir && data->IsSplitDirExplicit) ? overlay_col_drop_hovered
21634 : overlay_col_drop;
21635 for (
int overlay_n = 0; overlay_n < overlay_draw_lists_count; overlay_n++)
21637 ImVec2 center = ImFloor(draw_r_in.GetCenter());
21638 overlay_draw_lists[overlay_n]->AddRectFilled(draw_r.Min, draw_r.Max, overlay_col, overlay_rounding);
21639 overlay_draw_lists[overlay_n]->AddRect(draw_r_in.Min, draw_r_in.Max, overlay_col_lines,
21641 if (dir == ImGuiDir_Left || dir == ImGuiDir_Right)
21642 overlay_draw_lists[overlay_n]->AddLine(
ImVec2(center.x, draw_r_in.Min.y),
21643 ImVec2(center.x, draw_r_in.Max.y), overlay_col_lines);
21644 if (dir == ImGuiDir_Up || dir == ImGuiDir_Down)
21645 overlay_draw_lists[overlay_n]->AddLine(
ImVec2(draw_r_in.Min.x, center.y),
21646 ImVec2(draw_r_in.Max.x, center.y), overlay_col_lines);
21651 if ((host_node && (host_node->MergedFlags & ImGuiDockNodeFlags_NoDockingSplit)) || g.IO.ConfigDockingNoSplit)
21669 int split_inheritor_child_idx,
float split_ratio,
ImGuiDockNode *new_node)
21672 IM_ASSERT(split_axis != ImGuiAxis_None);
21674 ImGuiDockNode *child_0 = (new_node && split_inheritor_child_idx != 0) ? new_node : DockContextAddNode(ctx, 0);
21675 child_0->ParentNode = parent_node;
21677 ImGuiDockNode *child_1 = (new_node && split_inheritor_child_idx != 1) ? new_node : DockContextAddNode(ctx, 0);
21678 child_1->ParentNode = parent_node;
21680 ImGuiDockNode *child_inheritor = (split_inheritor_child_idx == 0) ? child_0 : child_1;
21681 DockNodeMoveChildNodes(child_inheritor, parent_node);
21682 parent_node->ChildNodes[0] = child_0;
21683 parent_node->ChildNodes[1] = child_1;
21684 parent_node->ChildNodes[split_inheritor_child_idx]->VisibleWindow = parent_node->VisibleWindow;
21685 parent_node->SplitAxis = split_axis;
21686 parent_node->VisibleWindow = NULL;
21687 parent_node->AuthorityForPos = parent_node->AuthorityForSize = ImGuiDataAuthority_DockNode;
21689 float size_avail = (parent_node->Size[split_axis] - g.Style.DockingSeparatorSize);
21690 size_avail = ImMax(size_avail, g.Style.WindowMinSize[split_axis] * 2.0f);
21691 IM_ASSERT(size_avail > 0.0f);
21693 child_0->SizeRef = child_1->SizeRef = parent_node->Size;
21694 child_0->SizeRef[split_axis] = ImTrunc(size_avail * split_ratio);
21695 child_1->SizeRef[split_axis] = ImTrunc(size_avail - child_0->SizeRef[split_axis]);
21697 DockNodeMoveWindows(parent_node->ChildNodes[split_inheritor_child_idx], parent_node);
21698 DockSettingsRenameNodeReferences(parent_node->ID, parent_node->ChildNodes[split_inheritor_child_idx]->ID);
21699 DockNodeUpdateHasCentralNodeChild(DockNodeGetRootNode(parent_node));
21700 DockNodeTreeUpdatePosSize(parent_node, parent_node->Pos, parent_node->Size);
21703 child_0->SharedFlags = parent_node->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
21704 child_1->SharedFlags = parent_node->SharedFlags & ImGuiDockNodeFlags_SharedFlagsInheritMask_;
21705 child_inheritor->LocalFlags = parent_node->LocalFlags & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
21706 parent_node->LocalFlags &= ~ImGuiDockNodeFlags_LocalFlagsTransferMask_;
21707 child_0->UpdateMergedFlags();
21708 child_1->UpdateMergedFlags();
21709 parent_node->UpdateMergedFlags();
21710 if (child_inheritor->IsCentralNode())
21711 DockNodeGetRootNode(parent_node)->CentralNode = child_inheritor;
21720 IM_ASSERT(child_0 || child_1);
21721 IM_ASSERT(merge_lead_child == child_0 || merge_lead_child == child_1);
21722 if ((child_0 && child_0->Windows.Size > 0) || (child_1 && child_1->Windows.Size > 0))
21724 IM_ASSERT(parent_node->TabBar == NULL);
21725 IM_ASSERT(parent_node->Windows.Size == 0);
21727 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockNodeTreeMerge: 0x%08X + 0x%08X back into parent 0x%08X\n",
21728 child_0 ? child_0->ID : 0, child_1 ? child_1->ID : 0, parent_node->ID);
21730 ImVec2 backup_last_explicit_size = parent_node->SizeRef;
21731 DockNodeMoveChildNodes(parent_node, merge_lead_child);
21734 DockNodeMoveWindows(parent_node, child_0);
21735 DockSettingsRenameNodeReferences(child_0->ID, parent_node->ID);
21739 DockNodeMoveWindows(parent_node, child_1);
21740 DockSettingsRenameNodeReferences(child_1->ID, parent_node->ID);
21742 DockNodeApplyPosSizeToWindows(parent_node);
21743 parent_node->AuthorityForPos = parent_node->AuthorityForSize = parent_node->AuthorityForViewport =
21744 ImGuiDataAuthority_Auto;
21745 parent_node->VisibleWindow = merge_lead_child->VisibleWindow;
21746 parent_node->SizeRef = backup_last_explicit_size;
21749 parent_node->LocalFlags &= ~ImGuiDockNodeFlags_LocalFlagsTransferMask_;
21750 parent_node->LocalFlags |= (child_0 ? child_0->LocalFlags : 0) & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
21751 parent_node->LocalFlags |= (child_1 ? child_1->LocalFlags : 0) & ImGuiDockNodeFlags_LocalFlagsTransferMask_;
21752 parent_node->LocalFlagsInWindows =
21753 (child_0 ? child_0->LocalFlagsInWindows : 0) |
21754 (child_1 ? child_1->LocalFlagsInWindows : 0);
21755 parent_node->UpdateMergedFlags();
21759 ctx->DockContext.Nodes.SetVoidPtr(child_0->ID, NULL);
21760 IM_DELETE(child_0);
21764 ctx->DockContext.Nodes.SetVoidPtr(child_1->ID, NULL);
21765 IM_DELETE(child_1);
21777 const bool write_to_node = only_write_to_single_node == NULL || only_write_to_single_node == node;
21784 if (node->IsLeafNode())
21789 ImVec2 child_0_pos = pos, child_1_pos = pos;
21790 ImVec2 child_0_size = size, child_1_size = size;
21792 const bool child_0_is_toward_single_node =
21793 (only_write_to_single_node != NULL && DockNodeIsInHierarchyOf(only_write_to_single_node, child_0));
21794 const bool child_1_is_toward_single_node =
21795 (only_write_to_single_node != NULL && DockNodeIsInHierarchyOf(only_write_to_single_node, child_1));
21796 const bool child_0_is_or_will_be_visible = child_0->IsVisible || child_0_is_toward_single_node;
21797 const bool child_1_is_or_will_be_visible = child_1->IsVisible || child_1_is_toward_single_node;
21799 if (child_0_is_or_will_be_visible && child_1_is_or_will_be_visible)
21801 const float spacing = g.Style.DockingSeparatorSize;
21802 const ImGuiAxis axis = (ImGuiAxis)node->SplitAxis;
21803 const float size_avail = ImMax(size[axis] - spacing, 0.0f);
21807 const float size_min_each = ImTrunc(ImMin(size_avail, g.Style.WindowMinSize[axis] * 2.0f) * 0.5f);
21815 if (child_0->WantLockSizeOnce && !child_1->WantLockSizeOnce)
21817 child_0_size[axis] = child_0->SizeRef[axis] = ImMin(size_avail - 1.0f, child_0->Size[axis]);
21818 child_1_size[axis] = child_1->SizeRef[axis] = (size_avail - child_0_size[axis]);
21819 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
21821 else if (child_1->WantLockSizeOnce && !child_0->WantLockSizeOnce)
21823 child_1_size[axis] = child_1->SizeRef[axis] = ImMin(size_avail - 1.0f, child_1->Size[axis]);
21824 child_0_size[axis] = child_0->SizeRef[axis] = (size_avail - child_1_size[axis]);
21825 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
21827 else if (child_0->WantLockSizeOnce && child_1->WantLockSizeOnce)
21831 float split_ratio = child_0_size[axis] / (child_0_size[axis] + child_1_size[axis]);
21832 child_0_size[axis] = child_0->SizeRef[axis] = ImTrunc(size_avail * split_ratio);
21833 child_1_size[axis] = child_1->SizeRef[axis] = (size_avail - child_0_size[axis]);
21834 IM_ASSERT(child_0->SizeRef[axis] > 0.0f && child_1->SizeRef[axis] > 0.0f);
21839 else if (child_0->SizeRef[axis] != 0.0f && child_1->HasCentralNodeChild)
21841 child_0_size[axis] = ImMin(size_avail - size_min_each, child_0->SizeRef[axis]);
21842 child_1_size[axis] = (size_avail - child_0_size[axis]);
21844 else if (child_1->SizeRef[axis] != 0.0f && child_0->HasCentralNodeChild)
21846 child_1_size[axis] = ImMin(size_avail - size_min_each, child_1->SizeRef[axis]);
21847 child_0_size[axis] = (size_avail - child_1_size[axis]);
21852 float split_ratio = child_0->SizeRef[axis] / (child_0->SizeRef[axis] + child_1->SizeRef[axis]);
21853 child_0_size[axis] = ImMax(size_min_each, ImTrunc(size_avail * split_ratio + 0.5f));
21854 child_1_size[axis] = (size_avail - child_0_size[axis]);
21857 child_1_pos[axis] += spacing + child_0_size[axis];
21860 if (only_write_to_single_node == NULL)
21861 child_0->WantLockSizeOnce = child_1->WantLockSizeOnce =
false;
21863 const bool child_0_recurse = only_write_to_single_node ? child_0_is_toward_single_node : child_0->IsVisible;
21864 const bool child_1_recurse = only_write_to_single_node ? child_1_is_toward_single_node : child_1->IsVisible;
21865 if (child_0_recurse)
21866 DockNodeTreeUpdatePosSize(child_0, child_0_pos, child_0_size);
21867 if (child_1_recurse)
21868 DockNodeTreeUpdatePosSize(child_1, child_1_pos, child_1_size);
21871static void DockNodeTreeUpdateSplitterFindTouchingNode(
ImGuiDockNode *node, ImGuiAxis axis,
int side,
21874 if (node->IsLeafNode())
21876 touching_nodes->push_back(node);
21879 if (node->ChildNodes[0]->IsVisible)
21880 if (node->SplitAxis != axis || side == 0 || !node->ChildNodes[1]->IsVisible)
21881 DockNodeTreeUpdateSplitterFindTouchingNode(node->ChildNodes[0], axis, side, touching_nodes);
21882 if (node->ChildNodes[1]->IsVisible)
21883 if (node->SplitAxis != axis || side == 1 || !node->ChildNodes[0]->IsVisible)
21884 DockNodeTreeUpdateSplitterFindTouchingNode(node->ChildNodes[1], axis, side, touching_nodes);
21890 if (node->IsLeafNode())
21897 if (child_0->IsVisible && child_1->IsVisible)
21901 const ImGuiAxis axis = (ImGuiAxis)node->SplitAxis;
21902 IM_ASSERT(axis != ImGuiAxis_None);
21904 bb.Min = child_0->Pos;
21905 bb.Max = child_1->Pos;
21906 bb.Min[axis] += child_0->Size[axis];
21907 bb.Max[axis ^ 1] += child_1->Size[axis ^ 1];
21911 const ImGuiDockNodeFlags merged_flags =
21912 child_0->MergedFlags | child_1->MergedFlags;
21913 const ImGuiDockNodeFlags no_resize_axis_flag =
21914 (axis == ImGuiAxis_X) ? ImGuiDockNodeFlags_NoResizeX : ImGuiDockNodeFlags_NoResizeY;
21915 if ((merged_flags & ImGuiDockNodeFlags_NoResize) || (merged_flags & no_resize_axis_flag))
21918 window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator), g.Style.FrameRounding);
21928 float min_size = g.Style.WindowMinSize[axis];
21929 float resize_limits[2];
21930 resize_limits[0] = node->ChildNodes[0]->Pos[axis] + min_size;
21931 resize_limits[1] = node->ChildNodes[1]->Pos[axis] + node->ChildNodes[1]->Size[axis] - min_size;
21933 ImGuiID splitter_id = GetID(
"##Splitter");
21934 if (g.ActiveId == splitter_id)
21936 DockNodeTreeUpdateSplitterFindTouchingNode(child_0, axis, 1, &touching_nodes[0]);
21937 DockNodeTreeUpdateSplitterFindTouchingNode(child_1, axis, 0, &touching_nodes[1]);
21938 for (
int touching_node_n = 0; touching_node_n < touching_nodes[0].Size; touching_node_n++)
21940 ImMax(resize_limits[0], touching_nodes[0][touching_node_n]->Rect().Min[axis] + min_size);
21941 for (
int touching_node_n = 0; touching_node_n < touching_nodes[1].Size; touching_node_n++)
21943 ImMin(resize_limits[1], touching_nodes[1][touching_node_n]->Rect().Max[axis] - min_size);
21964 float cur_size_0 = child_0->Size[axis];
21965 float cur_size_1 = child_1->Size[axis];
21966 float min_size_0 = resize_limits[0] - child_0->Pos[axis];
21967 float min_size_1 = child_1->Pos[axis] + child_1->Size[axis] - resize_limits[1];
21968 ImU32 bg_col = GetColorU32(ImGuiCol_WindowBg);
21969 if (SplitterBehavior(bb, GetID(
"##Splitter"), axis, &cur_size_0, &cur_size_1, min_size_0, min_size_1,
21970 g.WindowsBorderHoverPadding, WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER, bg_col))
21972 if (touching_nodes[0].Size > 0 && touching_nodes[1].Size > 0)
21974 child_0->Size[axis] = child_0->SizeRef[axis] = cur_size_0;
21975 child_1->Pos[axis] -= cur_size_1 - child_1->Size[axis];
21976 child_1->Size[axis] = child_1->SizeRef[axis] = cur_size_1;
21980 for (
int side_n = 0; side_n < 2; side_n++)
21981 for (
int touching_node_n = 0; touching_node_n < touching_nodes[side_n].Size; touching_node_n++)
21983 ImGuiDockNode *touching_node = touching_nodes[side_n][touching_node_n];
21987 while (touching_node->ParentNode != node)
21989 if (touching_node->ParentNode->SplitAxis == axis)
21993 ImGuiDockNode *node_to_preserve = touching_node->ParentNode->ChildNodes[side_n];
21994 node_to_preserve->WantLockSizeOnce =
true;
21999 touching_node = touching_node->ParentNode;
22003 DockNodeTreeUpdatePosSize(child_0, child_0->Pos, child_0->Size);
22004 DockNodeTreeUpdatePosSize(child_1, child_1->Pos, child_1->Size);
22005 MarkIniSettingsDirty();
22012 if (child_0->IsVisible)
22013 DockNodeTreeUpdateSplitter(child_0);
22014 if (child_1->IsVisible)
22015 DockNodeTreeUpdateSplitter(child_1);
22020 if (node->IsLeafNode())
22022 if (
ImGuiDockNode *leaf_node = DockNodeTreeFindFallbackLeafNode(node->ChildNodes[0]))
22024 if (
ImGuiDockNode *leaf_node = DockNodeTreeFindFallbackLeafNode(node->ChildNodes[1]))
22031 if (!node->IsVisible)
22034 const float dock_spacing = 0.0f;
22035 ImRect r(node->Pos, node->Pos + node->Size);
22036 r.Expand(dock_spacing * 0.5f);
22037 bool inside = r.Contains(pos);
22041 if (node->IsLeafNode())
22043 if (
ImGuiDockNode *hovered_node = DockNodeTreeFindVisibleNodeByPos(node->ChildNodes[0], pos))
22044 return hovered_node;
22045 if (
ImGuiDockNode *hovered_node = DockNodeTreeFindVisibleNodeByPos(node->ChildNodes[1], pos))
22046 return hovered_node;
22061void ImGui::SetWindowDock(
ImGuiWindow *window, ImGuiID dock_id, ImGuiCond cond)
22064 if (cond && (window->SetWindowDockAllowFlags & cond) == 0)
22066 window->SetWindowDockAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
22068 if (window->DockId == dock_id)
22073 if (
ImGuiDockNode *new_node = DockContextFindNodeByID(&g, dock_id))
22074 if (new_node->IsSplitNode())
22077 new_node = DockNodeGetRootNode(new_node);
22078 if (new_node->CentralNode)
22080 IM_ASSERT(new_node->CentralNode->IsCentralNode());
22081 dock_id = new_node->CentralNode->ID;
22085 dock_id = new_node->LastFocusedNodeId;
22089 if (window->DockId == dock_id)
22092 if (window->DockNode)
22093 DockNodeRemoveWindow(window->DockNode, window, 0);
22094 window->DockId = dock_id;
22102ImGuiID ImGui::DockSpace(ImGuiID dockspace_id,
const ImVec2 &size_arg, ImGuiDockNodeFlags flags,
22107 if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
22114 if (window->SkipItems)
22115 flags |= ImGuiDockNodeFlags_KeepAliveOnly;
22116 if ((flags & ImGuiDockNodeFlags_KeepAliveOnly) == 0)
22117 window = GetCurrentWindow();
22119 IM_ASSERT((flags & ImGuiDockNodeFlags_DockSpace) ==
22121 IM_ASSERT((flags & ImGuiDockNodeFlags_CentralNode) ==
22124 IM_ASSERT(dockspace_id != 0);
22125 ImGuiDockNode *node = DockContextFindNodeByID(&g, dockspace_id);
22128 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSpace: dockspace node 0x%08X created\n", dockspace_id);
22129 node = DockContextAddNode(&g, dockspace_id);
22130 node->SetLocalFlags(ImGuiDockNodeFlags_CentralNode);
22132 if (window_class && window_class->ClassId != node->WindowClass.ClassId)
22133 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSpace: dockspace node 0x%08X: setup WindowClass 0x%08X -> 0x%08X\n",
22134 dockspace_id, node->WindowClass.ClassId, window_class->ClassId);
22135 node->SharedFlags = flags;
22141 if (node->LastFrameActive == g.FrameCount && !(flags & ImGuiDockNodeFlags_KeepAliveOnly))
22143 IM_ASSERT(node->IsDockSpace() ==
false &&
"Cannot call DockSpace() twice a frame with the same ID");
22144 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_DockSpace);
22145 return dockspace_id;
22147 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_DockSpace);
22150 if (flags & ImGuiDockNodeFlags_KeepAliveOnly)
22152 node->LastFrameAlive = g.FrameCount;
22153 return dockspace_id;
22156 const ImVec2 content_avail = GetContentRegionAvail();
22157 ImVec2 size = ImTrunc(size_arg);
22158 if (size.x <= 0.0f)
22159 size.x = ImMax(content_avail.x + size.x, 4.0f);
22160 if (size.y <= 0.0f)
22161 size.y = ImMax(content_avail.y + size.y, 4.0f);
22162 IM_ASSERT(size.x > 0.0f && size.y > 0.0f);
22164 node->Pos = window->DC.CursorPos;
22165 node->Size = node->SizeRef = size;
22166 SetNextWindowPos(node->Pos);
22167 SetNextWindowSize(node->Size);
22168 g.NextWindowData.PosUndock =
false;
22172 ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_DockNodeHost;
22173 window_flags |= ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
22174 ImGuiWindowFlags_NoTitleBar;
22175 window_flags |= ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
22176 window_flags |= ImGuiWindowFlags_NoBackground;
22179 ImFormatString(title, IM_ARRAYSIZE(title),
"%s/DockSpace_%08X", window->Name, dockspace_id);
22181 PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.0f);
22182 Begin(title, NULL, window_flags);
22186 DockNodeSetupHostWindow(node, host_window);
22187 host_window->ChildId = window->GetID(title);
22188 node->OnlyNodeWithWindows = NULL;
22190 IM_ASSERT(node->IsRootNode());
22199 if (node->IsLeafNode() && !node->IsCentralNode())
22200 node->SetLocalFlags(node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
22203 DockNodeUpdate(node);
22207 ImRect bb(node->Pos, node->Pos + size);
22209 ItemAdd(bb, dockspace_id, NULL,
22210 ImGuiItemFlags_NoNav);
22212 if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) &&
22213 IsWindowChildOf(g.HoveredWindow, host_window,
false,
22215 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
22217 return dockspace_id;
22225ImGuiID ImGui::DockSpaceOverViewport(ImGuiID dockspace_id,
const ImGuiViewport *viewport,
22228 if (viewport == NULL)
22229 viewport = GetMainViewport();
22232 SetNextWindowPos(viewport->WorkPos);
22233 SetNextWindowSize(viewport->WorkSize);
22234 SetNextWindowViewport(viewport->ID);
22236 ImGuiWindowFlags host_window_flags = 0;
22237 host_window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
22238 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking;
22239 host_window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
22240 if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
22241 host_window_flags |= ImGuiWindowFlags_NoBackground;
22246 if (dockspace_flags & ImGuiDockNodeFlags_KeepAliveOnly)
22247 host_window_flags |= ImGuiWindowFlags_NoMouseInputs;
22250 ImFormatString(label, IM_ARRAYSIZE(label),
"WindowOverViewport_%08X", viewport->ID);
22252 PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
22253 PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
22254 PushStyleVar(ImGuiStyleVar_WindowPadding,
ImVec2(0.0f, 0.0f));
22255 Begin(label, NULL, host_window_flags);
22259 if (dockspace_id == 0)
22260 dockspace_id = GetID(
"DockSpace");
22261 DockSpace(dockspace_id,
ImVec2(0.0f, 0.0f), dockspace_flags, window_class);
22265 return dockspace_id;
22291void ImGui::DockBuilderDockWindow(
const char *window_name, ImGuiID node_id)
22296 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderDockWindow '%s' to node 0x%08X\n", window_name, node_id);
22297 ImGuiID window_id = ImHashStr(window_name);
22298 if (
ImGuiWindow *window = FindWindowByID(window_id))
22301 ImGuiID prev_node_id = window->DockId;
22302 SetWindowDock(window, node_id, ImGuiCond_Always);
22303 if (window->DockId != prev_node_id)
22304 window->DockOrder = -1;
22310 if (settings == NULL)
22311 settings = CreateNewWindowSettings(window_name);
22312 if (settings->DockId != node_id)
22313 settings->DockOrder = -1;
22314 settings->DockId = node_id;
22321 return DockContextFindNodeByID(&g, node_id);
22324void ImGui::DockBuilderSetNodePos(ImGuiID node_id,
ImVec2 pos)
22327 ImGuiDockNode *node = DockContextFindNodeByID(&g, node_id);
22331 node->AuthorityForPos = ImGuiDataAuthority_DockNode;
22334void ImGui::DockBuilderSetNodeSize(ImGuiID node_id,
ImVec2 size)
22337 ImGuiDockNode *node = DockContextFindNodeByID(&g, node_id);
22340 IM_ASSERT(size.x > 0.0f && size.y > 0.0f);
22341 node->Size = node->SizeRef = size;
22342 node->AuthorityForSize = ImGuiDataAuthority_DockNode;
22356ImGuiID ImGui::DockBuilderAddNode(ImGuiID node_id, ImGuiDockNodeFlags flags)
22360 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderAddNode 0x%08X flags=%08X\n", node_id, flags);
22363 DockBuilderRemoveNode(node_id);
22366 if (flags & ImGuiDockNodeFlags_DockSpace)
22368 DockSpace(node_id,
ImVec2(0, 0), (flags & ~ImGuiDockNodeFlags_DockSpace) | ImGuiDockNodeFlags_KeepAliveOnly);
22369 node = DockContextFindNodeByID(&g, node_id);
22373 node = DockContextAddNode(&g, node_id);
22374 node->SetLocalFlags(flags);
22376 node->LastFrameAlive = g.FrameCount;
22380void ImGui::DockBuilderRemoveNode(ImGuiID node_id)
22384 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderRemoveNode 0x%08X\n", node_id);
22386 ImGuiDockNode *node = DockContextFindNodeByID(&g, node_id);
22389 DockBuilderRemoveNodeDockedWindows(node_id,
true);
22390 DockBuilderRemoveNodeChildNodes(node_id);
22392 node = DockContextFindNodeByID(&g, node_id);
22395 if (node->IsCentralNode() && node->ParentNode)
22396 node->ParentNode->SetLocalFlags(node->ParentNode->LocalFlags | ImGuiDockNodeFlags_CentralNode);
22397 DockContextRemoveNode(&g, node,
true);
22401void ImGui::DockBuilderRemoveNodeChildNodes(ImGuiID root_id)
22406 ImGuiDockNode *root_node = root_id ? DockContextFindNodeByID(&g, root_id) : NULL;
22407 if (root_id && root_node == NULL)
22409 bool has_central_node =
false;
22411 ImGuiDataAuthority backup_root_node_authority_for_pos =
22412 root_node ? root_node->AuthorityForPos : ImGuiDataAuthority_Auto;
22413 ImGuiDataAuthority backup_root_node_authority_for_size =
22414 root_node ? root_node->AuthorityForSize : ImGuiDataAuthority_Auto;
22418 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
22421 bool want_removal = (root_id == 0) || (node->ID != root_id && DockNodeGetRootNode(node)->ID == root_id);
22424 if (node->IsCentralNode())
22425 has_central_node =
true;
22427 DockContextQueueNotifyRemovedNode(&g, node);
22430 DockNodeMoveWindows(root_node, node);
22431 DockSettingsRenameNodeReferences(node->ID, root_node->ID);
22433 nodes_to_remove.push_back(node);
22442 root_node->AuthorityForPos = backup_root_node_authority_for_pos;
22443 root_node->AuthorityForSize = backup_root_node_authority_for_size;
22448 settings = g.SettingsWindows.next_chunk(settings))
22449 if (ImGuiID window_settings_dock_id = settings->DockId)
22450 for (
int n = 0; n < nodes_to_remove.Size; n++)
22451 if (nodes_to_remove[n]->ID == window_settings_dock_id)
22453 settings->DockId = root_id;
22459 if (nodes_to_remove.Size > 1)
22460 ImQsort(nodes_to_remove.Data, nodes_to_remove.Size,
sizeof(
ImGuiDockNode *), DockNodeComparerDepthMostFirst);
22461 for (
int n = 0; n < nodes_to_remove.Size; n++)
22462 DockContextRemoveNode(&g, nodes_to_remove[n],
false);
22467 dc->Requests.clear();
22469 else if (has_central_node)
22471 root_node->CentralNode = root_node;
22472 root_node->SetLocalFlags(root_node->LocalFlags | ImGuiDockNodeFlags_CentralNode);
22476void ImGui::DockBuilderRemoveNodeDockedWindows(ImGuiID root_id,
bool clear_settings_refs)
22480 if (clear_settings_refs)
22483 settings = g.SettingsWindows.next_chunk(settings))
22485 bool want_removal = (root_id == 0) || (settings->DockId == root_id);
22486 if (!want_removal && settings->DockId != 0)
22487 if (
ImGuiDockNode *node = DockContextFindNodeByID(&g, settings->DockId))
22488 if (DockNodeGetRootNode(node)->ID == root_id)
22489 want_removal =
true;
22491 settings->DockId = 0;
22496 for (
int n = 0; n < g.Windows.Size; n++)
22499 bool want_removal = (root_id == 0) ||
22500 (window->DockNode && DockNodeGetRootNode(window->DockNode)->ID == root_id) ||
22501 (window->DockNodeAsHost && window->DockNodeAsHost->ID == root_id);
22504 const ImGuiID backup_dock_id = window->DockId;
22505 IM_UNUSED(backup_dock_id);
22506 DockContextProcessUndockWindow(&g, window, clear_settings_refs);
22507 if (!clear_settings_refs)
22508 IM_ASSERT(window->DockId == backup_dock_id);
22517ImGuiID ImGui::DockBuilderSplitNode(ImGuiID
id, ImGuiDir split_dir,
float size_ratio_for_node_at_dir,
22518 ImGuiID *out_id_at_dir, ImGuiID *out_id_at_opposite_dir)
22521 IM_ASSERT(split_dir != ImGuiDir_None);
22522 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockBuilderSplitNode: node 0x%08X, split_dir %d\n",
id, split_dir);
22527 IM_ASSERT(node != NULL);
22532 req.Type = ImGuiDockRequestType_Split;
22533 req.DockTargetWindow = NULL;
22534 req.DockTargetNode = node;
22535 req.DockPayload = NULL;
22536 req.DockSplitDir = split_dir;
22537 req.DockSplitRatio =
22538 ImSaturate((split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? size_ratio_for_node_at_dir
22539 : 1.0f - size_ratio_for_node_at_dir);
22540 req.DockSplitOuter =
false;
22541 DockContextProcessDock(&g, &req);
22543 ImGuiID id_at_dir = node->ChildNodes[(split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 0 : 1]->ID;
22544 ImGuiID id_at_opposite_dir = node->ChildNodes[(split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 1 : 0]->ID;
22546 *out_id_at_dir = id_at_dir;
22547 if (out_id_at_opposite_dir)
22548 *out_id_at_opposite_dir = id_at_opposite_dir;
22556 ImGuiDockNode *dst_node = ImGui::DockContextAddNode(&g, dst_node_id_if_known);
22557 dst_node->SharedFlags = src_node->SharedFlags;
22558 dst_node->LocalFlags = src_node->LocalFlags;
22559 dst_node->LocalFlagsInWindows = ImGuiDockNodeFlags_None;
22560 dst_node->Pos = src_node->Pos;
22561 dst_node->Size = src_node->Size;
22562 dst_node->SizeRef = src_node->SizeRef;
22563 dst_node->SplitAxis = src_node->SplitAxis;
22564 dst_node->UpdateMergedFlags();
22566 out_node_remap_pairs->push_back(src_node->ID);
22567 out_node_remap_pairs->push_back(dst_node->ID);
22569 for (
int child_n = 0; child_n < IM_ARRAYSIZE(src_node->ChildNodes); child_n++)
22570 if (src_node->ChildNodes[child_n])
22572 dst_node->ChildNodes[child_n] =
22573 DockBuilderCopyNodeRec(src_node->ChildNodes[child_n], 0, out_node_remap_pairs);
22574 dst_node->ChildNodes[child_n]->ParentNode = dst_node;
22577 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Fork node %08X -> %08X (%d childs)\n", src_node->ID, dst_node->ID,
22578 dst_node->IsSplitNode() ? 2 : 0);
22582void ImGui::DockBuilderCopyNode(ImGuiID src_node_id, ImGuiID dst_node_id,
ImVector<ImGuiID> *out_node_remap_pairs)
22585 IM_ASSERT(src_node_id != 0);
22586 IM_ASSERT(dst_node_id != 0);
22587 IM_ASSERT(out_node_remap_pairs != NULL);
22589 DockBuilderRemoveNode(dst_node_id);
22591 ImGuiDockNode *src_node = DockContextFindNodeByID(&g, src_node_id);
22592 IM_ASSERT(src_node != NULL);
22594 out_node_remap_pairs->clear();
22595 DockBuilderCopyNodeRec(src_node, dst_node_id, out_node_remap_pairs);
22597 IM_ASSERT((out_node_remap_pairs->Size % 2) == 0);
22600void ImGui::DockBuilderCopyWindowSettings(
const char *src_name,
const char *dst_name)
22602 ImGuiWindow *src_window = FindWindowByName(src_name);
22603 if (src_window == NULL)
22605 if (
ImGuiWindow *dst_window = FindWindowByName(dst_name))
22607 dst_window->Pos = src_window->Pos;
22608 dst_window->Size = src_window->Size;
22609 dst_window->SizeFull = src_window->SizeFull;
22610 dst_window->Collapsed = src_window->Collapsed;
22616 dst_settings = CreateNewWindowSettings(dst_name);
22618 if (src_window->ViewportId != 0 && src_window->ViewportId != IMGUI_VIEWPORT_DEFAULT_ID)
22620 dst_settings->ViewportPos = window_pos_2ih;
22621 dst_settings->ViewportId = src_window->ViewportId;
22622 dst_settings->Pos =
ImVec2ih(0, 0);
22626 dst_settings->Pos = window_pos_2ih;
22628 dst_settings->Size =
ImVec2ih(src_window->SizeFull);
22629 dst_settings->Collapsed = src_window->Collapsed;
22634void ImGui::DockBuilderCopyDockSpace(ImGuiID src_dockspace_id, ImGuiID dst_dockspace_id,
22638 IM_ASSERT(src_dockspace_id != 0);
22639 IM_ASSERT(dst_dockspace_id != 0);
22640 IM_ASSERT(in_window_remap_pairs != NULL);
22641 IM_ASSERT((in_window_remap_pairs->Size % 2) == 0);
22648 DockBuilderCopyNode(src_dockspace_id, dst_dockspace_id, &node_remap_pairs);
22653 for (
int remap_window_n = 0; remap_window_n < in_window_remap_pairs->Size; remap_window_n += 2)
22655 const char *src_window_name = (*in_window_remap_pairs)[remap_window_n];
22656 const char *dst_window_name = (*in_window_remap_pairs)[remap_window_n + 1];
22657 ImGuiID src_window_id = ImHashStr(src_window_name);
22658 src_windows.push_back(src_window_id);
22661 ImGuiID src_dock_id = 0;
22662 if (
ImGuiWindow *src_window = FindWindowByID(src_window_id))
22663 src_dock_id = src_window->DockId;
22664 else if (
ImGuiWindowSettings *src_window_settings = FindWindowSettingsByID(src_window_id))
22665 src_dock_id = src_window_settings->DockId;
22666 ImGuiID dst_dock_id = 0;
22667 for (
int dock_remap_n = 0; dock_remap_n < node_remap_pairs.Size; dock_remap_n += 2)
22668 if (node_remap_pairs[dock_remap_n] == src_dock_id)
22670 dst_dock_id = node_remap_pairs[dock_remap_n + 1];
22675 if (dst_dock_id != 0)
22678 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Remap live window '%s' 0x%08X -> '%s' 0x%08X\n", src_window_name,
22679 src_dock_id, dst_window_name, dst_dock_id);
22680 DockBuilderDockWindow(dst_window_name, dst_dock_id);
22687 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Remap window settings '%s' -> '%s'\n", src_window_name, dst_window_name);
22688 DockBuilderCopyWindowSettings(src_window_name, dst_window_name);
22695 struct DockRemainingWindowTask
22699 DockRemainingWindowTask(
ImGuiWindow *window, ImGuiID dock_id)
22706 for (
int dock_remap_n = 0; dock_remap_n < node_remap_pairs.Size; dock_remap_n += 2)
22707 if (ImGuiID src_dock_id = node_remap_pairs[dock_remap_n])
22709 ImGuiID dst_dock_id = node_remap_pairs[dock_remap_n + 1];
22711 for (
int window_n = 0; window_n < node->Windows.Size; window_n++)
22714 if (src_windows.contains(window->ID))
22718 IMGUI_DEBUG_LOG_DOCKING(
"[docking] Remap window '%s' %08X -> %08X\n", window->Name, src_dock_id,
22720 dock_remaining_windows.push_back(DockRemainingWindowTask(window, dst_dock_id));
22723 for (
const DockRemainingWindowTask &task : dock_remaining_windows)
22724 DockBuilderDockWindow(task.Window->Name, task.DockId);
22728void ImGui::DockBuilderFinish(ImGuiID root_id)
22732 DockContextBuildAddWindowsToNodes(&g, root_id);
22745bool ImGui::GetWindowAlwaysWantOwnTabBar(
ImGuiWindow *window)
22748 if (g.IO.ConfigDockingAlwaysTabBar || window->WindowClass.DockingAlwaysTabBar)
22749 if ((window->Flags &
22750 (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking)) == 0)
22751 if (!window->IsFallbackWindow)
22760 ImGuiDockNode *node = DockContextFindNodeByID(ctx, window->DockId);
22761 IM_ASSERT(window->DockNode == NULL);
22764 if (node && node->IsSplitNode())
22766 DockContextProcessUndockWindow(ctx, window);
22773 node = DockContextAddNode(ctx, window->DockId);
22774 node->AuthorityForPos = node->AuthorityForSize = node->AuthorityForViewport = ImGuiDataAuthority_Window;
22775 node->LastFrameAlive = g.FrameCount;
22783 if (!node->IsVisible)
22786 while (!ancestor_node->IsVisible && ancestor_node->ParentNode)
22787 ancestor_node = ancestor_node->ParentNode;
22788 IM_ASSERT(ancestor_node->Size.x > 0.0f && ancestor_node->Size.y > 0.0f);
22789 DockNodeUpdateHasCentralNodeChild(DockNodeGetRootNode(ancestor_node));
22790 DockNodeTreeUpdatePosSize(ancestor_node, ancestor_node->Pos, ancestor_node->Size, node);
22794 bool node_was_visible = node->IsVisible;
22795 DockNodeAddWindow(node, window,
true);
22796 node->IsVisible = node_was_visible;
22798 IM_ASSERT(node == window->DockNode);
22802static void StoreDockStyleForWindow(
ImGuiWindow *window)
22805 for (
int color_n = 0; color_n < ImGuiWindowDockStyleCol_COUNT; color_n++)
22806 window->DockStyle.Colors[color_n] =
22807 ImGui::ColorConvertFloat4ToU32(g.Style.Colors[GWindowDockStyleColors[color_n]]);
22810void ImGui::BeginDocked(
ImGuiWindow *window,
bool *p_open)
22815 window->DockIsActive = window->DockNodeIsVisible = window->DockTabIsVisible =
false;
22817 const bool auto_dock_node = GetWindowAlwaysWantOwnTabBar(window);
22818 if (auto_dock_node)
22820 if (window->DockId == 0)
22822 IM_ASSERT(window->DockNode == NULL);
22823 window->DockId = DockContextGenNodeID(&g);
22829 bool want_undock =
false;
22830 want_undock |= (window->Flags & ImGuiWindowFlags_NoDocking) != 0;
22831 want_undock |= (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos) &&
22832 (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) && g.NextWindowData.PosUndock;
22835 DockContextProcessUndockWindow(&g, window);
22843 IM_ASSERT(window->DockId == node->ID);
22844 if (window->DockId != 0 && node == NULL)
22846 node = DockContextBindNodeToWindow(&g, window);
22853 if (node->IsCentralNode && (node->Flags & ImGuiDockNodeFlags_NoDockingInCentralNode))
22855 DockContextProcessUndockWindow(ctx, window);
22863 if (node->LastFrameAlive < g.FrameCount)
22868 if (root_node->LastFrameAlive < g.FrameCount)
22869 DockContextProcessUndockWindow(&g, window);
22871 window->DockIsActive =
true;
22876 StoreDockStyleForWindow(window);
22882 if (node->HostWindow == NULL)
22884 if (node->State == ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing)
22885 window->DockIsActive =
true;
22886 if (node->Windows.Size > 1 && window->Appearing)
22887 DockNodeHideWindowDuringHostWindowCreation(window);
22892 IM_ASSERT(node->HostWindow);
22893 IM_ASSERT(node->IsLeafNode());
22894 IM_ASSERT(node->Size.x >= 0.0f && node->Size.y >= 0.0f);
22895 node->State = ImGuiDockNodeState_HostWindowVisible;
22898 if (!(node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly) &&
22899 window->BeginOrderWithinContext < node->HostWindow->BeginOrderWithinContext)
22901 DockContextProcessUndockWindow(&g, window);
22906 SetNextWindowPos(node->Pos);
22907 SetNextWindowSize(node->Size);
22908 g.NextWindowData.PosUndock =
false;
22909 window->DockIsActive =
true;
22910 window->DockNodeIsVisible =
true;
22911 window->DockTabIsVisible =
false;
22912 if (node->MergedFlags & ImGuiDockNodeFlags_KeepAliveOnly)
22916 if (node->VisibleWindow == window)
22917 window->DockTabIsVisible =
true;
22920 IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) == 0);
22921 window->Flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize;
22922 window->ChildFlags |= ImGuiChildFlags_AlwaysUseWindowPadding;
22923 if (node->IsHiddenTabBar() || node->IsNoTabBar())
22924 window->Flags |= ImGuiWindowFlags_NoTitleBar;
22926 window->Flags &= ~ImGuiWindowFlags_NoTitleBar;
22932 if (node->TabBar && window->WasActive)
22933 window->DockOrder = (short)DockNodeGetTabOrder(window);
22935 if ((node->WantCloseAll || node->WantCloseTabId == window->TabId) && p_open != NULL)
22939 ImGuiWindow *parent_window = window->DockNode->HostWindow;
22940 window->ChildId = parent_window->GetID(window->Name);
22943void ImGui::BeginDockableDragDropSource(
ImGuiWindow *window)
22946 IM_ASSERT(g.ActiveId == window->MoveId);
22947 IM_ASSERT(g.MovingWindow == window);
22948 IM_ASSERT(g.CurrentWindow == window);
22951 if (g.IO.ConfigDockingWithShift != g.IO.KeyShift)
22957 IM_ASSERT(g.NextWindowData.HasFlags == 0);
22958 if (g.IO.ConfigDockingWithShift && g.MouseStationaryTimer >= 1.0f && g.ActiveId >= 1.0f)
22959 SetTooltip(
"%s", LocalizeGetMsg(ImGuiLocKey_DockingHoldShiftToDock));
22963 g.LastItemData.ID = window->MoveId;
22964 window = window->RootWindowDockTree;
22965 IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
22966 bool is_drag_docking =
22967 (g.IO.ConfigDockingWithShift) ||
22968 ImRect(0, 0, window->SizeFull.x, GetFrameHeight())
22969 .Contains(g.ActiveIdClickOffset);
22970 ImGuiDragDropFlags drag_drop_flags =
22971 ImGuiDragDropFlags_SourceNoPreviewTooltip | ImGuiDragDropFlags_SourceNoHoldToOpenOthers |
22972 ImGuiDragDropFlags_PayloadAutoExpire | ImGuiDragDropFlags_PayloadNoCrossContext |
22973 ImGuiDragDropFlags_PayloadNoCrossProcess;
22974 if (is_drag_docking && BeginDragDropSource(drag_drop_flags))
22976 SetDragDropPayload(IMGUI_PAYLOAD_TYPE_WINDOW, &window,
sizeof(window));
22977 EndDragDropSource();
22978 StoreDockStyleForWindow(
22983void ImGui::BeginDockableDragDropTarget(
ImGuiWindow *window)
22988 IM_ASSERT((window->Flags & ImGuiWindowFlags_NoDocking) == 0);
22989 if (!g.DragDropActive)
22992 if (!BeginDragDropTargetCustom(window->Rect(), window->ID))
22998 if (!payload->IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) ||
22999 !DockNodeIsDropAllowed(window, *(
ImGuiWindow **)payload->Data))
23001 EndDragDropTarget();
23006 if (AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_WINDOW,
23007 ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect))
23012 bool dock_into_floating_window =
false;
23014 if (window->DockNodeAsHost)
23018 node = DockNodeTreeFindVisibleNodeByPos(window->DockNodeAsHost, g.IO.MousePos);
23023 if (node && node->IsDockSpace() && node->IsRootNode())
23024 node = (node->CentralNode && node->IsLeafNode()) ? node->CentralNode
23025 : DockNodeTreeFindFallbackLeafNode(node);
23029 if (window->DockNode)
23030 node = window->DockNode;
23032 dock_into_floating_window =
true;
23035 const ImRect explicit_target_rect =
23036 (node && node->TabBar && !node->IsHiddenTabBar() && !node->IsNoTabBar())
23037 ? node->TabBar->BarRect
23038 :
ImRect(window->Pos, window->Pos +
ImVec2(window->Size.x, GetFrameHeight()));
23039 const bool is_explicit_target =
23040 g.IO.ConfigDockingWithShift || IsMouseHoveringRect(explicit_target_rect.Min, explicit_target_rect.Max);
23045 const bool do_preview = payload->IsPreview() || payload->IsDelivery();
23046 if (do_preview && (node != NULL || dock_into_floating_window))
23053 if (node && (node->ParentNode || node->IsCentralNode() || !node->IsLeafNode()))
23056 DockNodePreviewDockSetup(window, root_node, payload_window, NULL, &split_outer, is_explicit_target,
23058 if (split_outer.IsSplitDirExplicit)
23059 split_data = &split_outer;
23061 if (!node || node->IsLeafNode())
23062 DockNodePreviewDockSetup(window, node, payload_window, NULL, &split_inner, is_explicit_target,
false);
23063 if (split_data == &split_outer)
23064 split_inner.IsDropAllowed =
false;
23067 DockNodePreviewDockRender(window, node, payload_window, &split_inner);
23068 DockNodePreviewDockRender(window, node, payload_window, &split_outer);
23071 if (split_data->IsDropAllowed && payload->IsDelivery())
23072 DockContextQueueDock(&g, window, split_data->SplitNode, payload_window, split_data->SplitDir,
23073 split_data->SplitRatio, split_data == &split_outer);
23076 EndDragDropTarget();
23092static void ImGui::DockSettingsRenameNodeReferences(ImGuiID old_node_id, ImGuiID new_node_id)
23095 IMGUI_DEBUG_LOG_DOCKING(
"[docking] DockSettingsRenameNodeReferences: from 0x%08X -> to 0x%08X\n", old_node_id,
23097 for (
int window_n = 0; window_n < g.Windows.Size; window_n++)
23100 if (window->DockId == old_node_id && window->DockNode == NULL)
23101 window->DockId = new_node_id;
23105 settings = g.SettingsWindows.next_chunk(settings))
23106 if (settings->DockId == old_node_id)
23107 settings->DockId = new_node_id;
23111static void ImGui::DockSettingsRemoveNodeReferences(ImGuiID *node_ids,
int node_ids_count)
23117 settings = g.SettingsWindows.next_chunk(settings))
23118 for (
int node_n = 0; node_n < node_ids_count; node_n++)
23119 if (settings->DockId == node_ids[node_n])
23121 settings->DockId = 0;
23122 settings->DockOrder = -1;
23123 if (++found < node_ids_count)
23133 for (
int n = 0; n < dc->NodesSettings.Size; n++)
23134 if (dc->NodesSettings[n].ID ==
id)
23135 return &dc->NodesSettings[n];
23143 dc->NodesSettings.clear();
23144 DockContextClearNodes(ctx, 0,
true);
23152 if (ctx->Windows.Size == 0)
23153 DockContextPruneUnusedSettingsNodes(ctx);
23154 DockContextBuildNodesFromSettings(ctx, dc->NodesSettings.Data, dc->NodesSettings.Size);
23155 DockContextBuildAddWindowsToNodes(ctx, 0);
23160 if (strcmp(name,
"Data") != 0)
23176 line = ImStrSkipBlank(line);
23177 if (strncmp(line,
"DockNode", 8) == 0)
23179 line = ImStrSkipBlank(line + strlen(
"DockNode"));
23181 else if (strncmp(line,
"DockSpace", 9) == 0)
23183 line = ImStrSkipBlank(line + strlen(
"DockSpace"));
23184 node.Flags |= ImGuiDockNodeFlags_DockSpace;
23188 if (sscanf(line,
"ID=0x%08X%n", &node.ID, &r) == 1)
23194 if (sscanf(line,
" Parent=0x%08X%n", &node.ParentNodeId, &r) == 1)
23197 if (node.ParentNodeId == 0)
23200 if (sscanf(line,
" Window=0x%08X%n", &node.ParentWindowId, &r) == 1)
23203 if (node.ParentWindowId == 0)
23206 if (node.ParentNodeId == 0)
23208 if (sscanf(line,
" Pos=%i,%i%n", &x, &y, &r) == 2)
23211 node.Pos =
ImVec2ih((
short)x, (
short)y);
23215 if (sscanf(line,
" Size=%i,%i%n", &x, &y, &r) == 2)
23218 node.Size =
ImVec2ih((
short)x, (
short)y);
23225 if (sscanf(line,
" SizeRef=%i,%i%n", &x, &y, &r) == 2)
23228 node.SizeRef =
ImVec2ih((
short)x, (
short)y);
23231 if (sscanf(line,
" Split=%c%n", &c, &r) == 1)
23235 node.SplitAxis = ImGuiAxis_X;
23237 node.SplitAxis = ImGuiAxis_Y;
23239 if (sscanf(line,
" NoResize=%d%n", &x, &r) == 1)
23243 node.Flags |= ImGuiDockNodeFlags_NoResize;
23245 if (sscanf(line,
" CentralNode=%d%n", &x, &r) == 1)
23249 node.Flags |= ImGuiDockNodeFlags_CentralNode;
23251 if (sscanf(line,
" NoTabBar=%d%n", &x, &r) == 1)
23255 node.Flags |= ImGuiDockNodeFlags_NoTabBar;
23257 if (sscanf(line,
" HiddenTabBar=%d%n", &x, &r) == 1)
23261 node.Flags |= ImGuiDockNodeFlags_HiddenTabBar;
23263 if (sscanf(line,
" NoWindowMenuButton=%d%n", &x, &r) == 1)
23267 node.Flags |= ImGuiDockNodeFlags_NoWindowMenuButton;
23269 if (sscanf(line,
" NoCloseButton=%d%n", &x, &r) == 1)
23273 node.Flags |= ImGuiDockNodeFlags_NoCloseButton;
23275 if (sscanf(line,
" Selected=0x%08X%n", &node.SelectedTabId, &r) == 1)
23279 if (node.ParentNodeId != 0)
23281 node.Depth = parent_settings->Depth + 1;
23282 ctx->DockContext.NodesSettings.push_back(node);
23288 IM_ASSERT(depth < (1 << (
sizeof(node_settings.Depth) << 3)));
23289 node_settings.ID = node->ID;
23290 node_settings.ParentNodeId = node->ParentNode ? node->ParentNode->ID : 0;
23291 node_settings.ParentWindowId = (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow)
23292 ? node->HostWindow->ParentWindow->ID
23294 node_settings.SelectedTabId = node->SelectedTabId;
23295 node_settings.SplitAxis = (
signed char)(node->IsSplitNode() ? node->SplitAxis : ImGuiAxis_None);
23296 node_settings.Depth = (char)depth;
23297 node_settings.Flags = (node->LocalFlags & ImGuiDockNodeFlags_SavedFlagsMask_);
23298 node_settings.Pos =
ImVec2ih(node->Pos);
23299 node_settings.Size =
ImVec2ih(node->Size);
23300 node_settings.SizeRef =
ImVec2ih(node->SizeRef);
23301 dc->NodesSettings.push_back(node_settings);
23302 if (node->ChildNodes[0])
23303 DockSettingsHandler_DockNodeToSettings(dc, node->ChildNodes[0], depth + 1);
23304 if (node->ChildNodes[1])
23305 DockSettingsHandler_DockNodeToSettings(dc, node->ChildNodes[1], depth + 1);
23312 if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
23317 dc->NodesSettings.resize(0);
23318 dc->NodesSettings.reserve(dc->Nodes.Data.Size);
23319 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
23321 if (node->IsRootNode())
23322 DockSettingsHandler_DockNodeToSettings(dc, node, 0);
23325 for (
int node_n = 0; node_n < dc->NodesSettings.Size; node_n++)
23326 max_depth = ImMax((
int)dc->NodesSettings[node_n].Depth, max_depth);
23329 buf->appendf(
"[%s][Data]\n", handler->TypeName);
23330 for (
int node_n = 0; node_n < dc->NodesSettings.Size; node_n++)
23332 const int line_start_pos = buf->size();
23333 (void)line_start_pos;
23335 buf->appendf(
"%*s%s%*s", node_settings->Depth * 2,
"",
23336 (node_settings->Flags & ImGuiDockNodeFlags_DockSpace) ?
"DockSpace" :
"DockNode ",
23337 (max_depth - node_settings->Depth) * 2,
"");
23338 buf->appendf(
" ID=0x%08X", node_settings->ID);
23339 if (node_settings->ParentNodeId)
23341 buf->appendf(
" Parent=0x%08X SizeRef=%d,%d", node_settings->ParentNodeId, node_settings->SizeRef.x,
23342 node_settings->SizeRef.y);
23346 if (node_settings->ParentWindowId)
23347 buf->appendf(
" Window=0x%08X", node_settings->ParentWindowId);
23348 buf->appendf(
" Pos=%d,%d Size=%d,%d", node_settings->Pos.x, node_settings->Pos.y, node_settings->Size.x,
23349 node_settings->Size.y);
23351 if (node_settings->SplitAxis != ImGuiAxis_None)
23352 buf->appendf(
" Split=%c", (node_settings->SplitAxis == ImGuiAxis_X) ?
'X' :
'Y');
23353 if (node_settings->Flags & ImGuiDockNodeFlags_NoResize)
23354 buf->appendf(
" NoResize=1");
23355 if (node_settings->Flags & ImGuiDockNodeFlags_CentralNode)
23356 buf->appendf(
" CentralNode=1");
23357 if (node_settings->Flags & ImGuiDockNodeFlags_NoTabBar)
23358 buf->appendf(
" NoTabBar=1");
23359 if (node_settings->Flags & ImGuiDockNodeFlags_HiddenTabBar)
23360 buf->appendf(
" HiddenTabBar=1");
23361 if (node_settings->Flags & ImGuiDockNodeFlags_NoWindowMenuButton)
23362 buf->appendf(
" NoWindowMenuButton=1");
23363 if (node_settings->Flags & ImGuiDockNodeFlags_NoCloseButton)
23364 buf->appendf(
" NoCloseButton=1");
23365 if (node_settings->SelectedTabId)
23366 buf->appendf(
" Selected=0x%08X", node_settings->SelectedTabId);
23369 if (g.IO.ConfigDebugIniSettings)
23370 if (
ImGuiDockNode *node = DockContextFindNodeByID(ctx, node_settings->ID))
23372 buf->appendf(
"%*s", ImMax(2, (line_start_pos + 92) - buf->size()),
"");
23373 if (node->IsDockSpace() && node->HostWindow && node->HostWindow->ParentWindow)
23374 buf->appendf(
" ; in '%s'", node->HostWindow->ParentWindow->Name);
23376 int contains_window = 0;
23378 settings = g.SettingsWindows.next_chunk(settings))
23379 if (settings->DockId == node_settings->ID)
23381 if (contains_window++ == 0)
23382 buf->appendf(
" ; contains ");
23383 buf->appendf(
"'%s' ", settings->GetName());
23387 buf->appendf(
"\n");
23389 buf->appendf(
"\n");
23400#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && \
23401 !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS)
23404#pragma comment(lib, "user32")
23405#pragma comment(lib, "kernel32")
23410static const char *Platform_GetClipboardTextFn_DefaultImpl(
ImGuiContext *ctx)
23413 g.ClipboardHandlerData.clear();
23414 if (!::OpenClipboard(NULL))
23416 HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT);
23417 if (wbuf_handle == NULL)
23419 ::CloseClipboard();
23422 if (
const WCHAR *wbuf_global = (
const WCHAR *)::GlobalLock(wbuf_handle))
23424 int buf_len = ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, NULL, 0, NULL, NULL);
23425 g.ClipboardHandlerData.resize(buf_len);
23426 ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, g.ClipboardHandlerData.Data, buf_len, NULL, NULL);
23428 ::GlobalUnlock(wbuf_handle);
23429 ::CloseClipboard();
23430 return g.ClipboardHandlerData.Data;
23433static void Platform_SetClipboardTextFn_DefaultImpl(
ImGuiContext *,
const char *text)
23435 if (!::OpenClipboard(NULL))
23437 const int wbuf_length = ::MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
23438 HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length *
sizeof(WCHAR));
23439 if (wbuf_handle == NULL)
23441 ::CloseClipboard();
23444 WCHAR *wbuf_global = (WCHAR *)::GlobalLock(wbuf_handle);
23445 ::MultiByteToWideChar(CP_UTF8, 0, text, -1, wbuf_global, wbuf_length);
23446 ::GlobalUnlock(wbuf_handle);
23447 ::EmptyClipboard();
23448 if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
23449 ::GlobalFree(wbuf_handle);
23450 ::CloseClipboard();
23453#elif defined(__APPLE__) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS)
23455#include <Carbon/Carbon.h>
23456static PasteboardRef main_clipboard = 0;
23460static void Platform_SetClipboardTextFn_DefaultImpl(
ImGuiContext *,
const char *text)
23462 if (!main_clipboard)
23463 PasteboardCreate(kPasteboardClipboard, &main_clipboard);
23464 PasteboardClear(main_clipboard);
23465 CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (
const UInt8 *)text, ImStrlen(text));
23468 PasteboardPutItemFlavor(main_clipboard, (PasteboardItemID)1, CFSTR(
"public.utf8-plain-text"), cf_data, 0);
23469 CFRelease(cf_data);
23473static const char *Platform_GetClipboardTextFn_DefaultImpl(
ImGuiContext *ctx)
23476 if (!main_clipboard)
23477 PasteboardCreate(kPasteboardClipboard, &main_clipboard);
23478 PasteboardSynchronize(main_clipboard);
23480 ItemCount item_count = 0;
23481 PasteboardGetItemCount(main_clipboard, &item_count);
23482 for (ItemCount i = 0; i < item_count; i++)
23484 PasteboardItemID item_id = 0;
23485 PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id);
23486 CFArrayRef flavor_type_array = 0;
23487 PasteboardCopyItemFlavors(main_clipboard, item_id, &flavor_type_array);
23488 for (CFIndex j = 0, nj = CFArrayGetCount(flavor_type_array); j < nj; j++)
23491 if (PasteboardCopyItemFlavorData(main_clipboard, item_id, CFSTR(
"public.utf8-plain-text"), &cf_data) ==
23494 g.ClipboardHandlerData.clear();
23495 int length = (int)CFDataGetLength(cf_data);
23496 g.ClipboardHandlerData.resize(length + 1);
23497 CFDataGetBytes(cf_data, CFRangeMake(0, length), (UInt8 *)g.ClipboardHandlerData.Data);
23498 g.ClipboardHandlerData[length] = 0;
23499 CFRelease(cf_data);
23500 return g.ClipboardHandlerData.Data;
23510static const char *Platform_GetClipboardTextFn_DefaultImpl(
ImGuiContext *ctx)
23513 return g.ClipboardHandlerData.empty() ? NULL : g.ClipboardHandlerData.begin();
23516static void Platform_SetClipboardTextFn_DefaultImpl(
ImGuiContext *ctx,
const char *text)
23519 g.ClipboardHandlerData.clear();
23520 const char *text_end = text + ImStrlen(text);
23521 g.ClipboardHandlerData.resize((
int)(text_end - text) + 1);
23522 memcpy(&g.ClipboardHandlerData[0], text, (
size_t)(text_end - text));
23523 g.ClipboardHandlerData[(int)(text_end - text)] = 0;
23530#ifndef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
23531#if defined(__APPLE__) && TARGET_OS_IPHONE
23532#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
23534#if defined(__3DS__)
23535#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
23537#if defined(_WIN32) && defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
23538#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
23542#ifndef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS
23544#include <shellapi.h>
23546#pragma comment(lib, "shell32")
23548static bool Platform_OpenInShellFn_DefaultImpl(
ImGuiContext *,
const char *path)
23550 const int path_wsize = ::MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
23552 path_wbuf.resize(path_wsize);
23553 ::MultiByteToWideChar(CP_UTF8, 0, path, -1, path_wbuf.Data, path_wsize);
23554 return (INT_PTR)::ShellExecuteW(NULL, L
"open", path_wbuf.Data, NULL, NULL, SW_SHOWDEFAULT) > 32;
23557#include <sys/wait.h>
23559static bool Platform_OpenInShellFn_DefaultImpl(
ImGuiContext *,
const char *path)
23561#if defined(__APPLE__)
23562 const char *args[]{
"open",
"--", path, NULL};
23564 const char *args[]{
"xdg-open", path, NULL};
23566 pid_t pid = fork();
23571 execvp(args[0],
const_cast<char **
>(args));
23577 waitpid(pid, &status, 0);
23578 return WEXITSTATUS(status) == 0;
23583static bool Platform_OpenInShellFn_DefaultImpl(
ImGuiContext *,
const char *)
23592#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
23596#pragma comment(lib, "imm32")
23602 HWND hwnd = (HWND)viewport->PlatformHandleRaw;
23607 if (HIMC himc = ::ImmGetContext(hwnd))
23609 COMPOSITIONFORM composition_form = {};
23610 composition_form.ptCurrentPos.x = (LONG)(data->InputPos.x - viewport->Pos.x);
23611 composition_form.ptCurrentPos.y = (LONG)(data->InputPos.y - viewport->Pos.y);
23612 composition_form.dwStyle = CFS_FORCE_POSITION;
23613 ::ImmSetCompositionWindow(himc, &composition_form);
23614 CANDIDATEFORM candidate_form = {};
23615 candidate_form.dwStyle = CFS_CANDIDATEPOS;
23616 candidate_form.ptCurrentPos.x = (LONG)(data->InputPos.x - viewport->Pos.x);
23617 candidate_form.ptCurrentPos.y = (LONG)(data->InputPos.y - viewport->Pos.y);
23618 ::ImmSetCandidateWindow(himc, &candidate_form);
23619 ::ImmReleaseContext(hwnd, himc);
23655#ifndef IMGUI_DISABLE_DEBUG_TOOLS
23662 ImVec2 scale = bb.GetSize() / viewport->Size;
23663 ImVec2 off = bb.Min - viewport->Pos * scale;
23664 float alpha_mul = (viewport->Flags & ImGuiViewportFlags_IsMinimized) ? 0.30f : 1.00f;
23665 window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f));
23668 if (!thumb_window->WasActive || (thumb_window->Flags & ImGuiWindowFlags_ChildWindow))
23670 if (thumb_window->Viewport != viewport)
23673 ImRect thumb_r = thumb_window->Rect();
23674 ImRect title_r = thumb_window->TitleBarRect();
23675 thumb_r =
ImRect(ImTrunc(off + thumb_r.Min * scale), ImTrunc(off + thumb_r.Max * scale));
23676 title_r =
ImRect(ImTrunc(off + title_r.Min * scale),
23677 ImTrunc(off +
ImVec2(title_r.Max.x, title_r.Min.y + title_r.GetHeight() * 3.0f) *
23679 thumb_r.ClipWithFull(bb);
23680 title_r.ClipWithFull(bb);
23681 const bool window_is_focused = (g.NavWindow && thumb_window->RootWindowForTitleBarHighlight ==
23682 g.NavWindow->RootWindowForTitleBarHighlight);
23683 window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul));
23684 window->DrawList->AddRectFilled(
23685 title_r.Min, title_r.Max,
23686 GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul));
23687 window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
23688 window->DrawList->AddText(g.Font, g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul),
23689 thumb_window->Name, FindRenderedTextEnd(thumb_window->Name));
23691 draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
23692 if (viewport->ID == g.DebugMetricsConfig.HighlightViewportID)
23693 window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
23696static void RenderViewportsThumbnails()
23702 float SCALE = 1.0f / 8.0f;
23703 ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
23705 bb_full.Add(
ImRect(monitor.MainPos, monitor.MainPos + monitor.MainSize));
23706 ImVec2 p = window->DC.CursorPos;
23707 ImVec2 off = p - bb_full.Min * SCALE;
23710 ImRect monitor_draw_bb(off + (monitor.MainPos) * SCALE, off + (monitor.MainPos + monitor.MainSize) * SCALE);
23711 window->DrawList->AddRect(
23712 monitor_draw_bb.Min, monitor_draw_bb.Max,
23713 (g.DebugMetricsConfig.HighlightMonitorIdx == g.PlatformIO.Monitors.index_from_ptr(&monitor))
23714 ? IM_COL32(255, 255, 0, 255)
23715 : ImGui::GetColorU32(ImGuiCol_Border),
23717 window->DrawList->AddRectFilled(monitor_draw_bb.Min, monitor_draw_bb.Max,
23718 ImGui::GetColorU32(ImGuiCol_Border, 0.10f), 4.0f);
23724 ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE);
23725 ImGui::DebugRenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb);
23727 ImGui::Dummy(bb_full.GetSize() * SCALE);
23730static int IMGUI_CDECL ViewportComparerByLastFocusedStampCount(
const void *lhs,
const void *rhs)
23734 return b->LastFocusedStampCount - a->LastFocusedStampCount;
23738void ImGui::DebugRenderKeyboardPreview(
ImDrawList *draw_list)
23740 const float scale = ImGui::GetFontSize() / 13.0f;
23742 const float key_rounding = 3.0f * scale;
23743 const ImVec2 key_face_size =
ImVec2(25.0f, 25.0f) * scale;
23744 const ImVec2 key_face_pos =
ImVec2(5.0f, 3.0f) * scale;
23745 const float key_face_rounding = 2.0f * scale;
23746 const ImVec2 key_label_pos =
ImVec2(7.0f, 4.0f) * scale;
23747 const ImVec2 key_step =
ImVec2(key_size.x - 1.0f, key_size.y - 1.0f);
23748 const float key_row_offset = 9.0f * scale;
23750 ImVec2 board_min = GetCursorScreenPos();
23752 ImVec2(board_min.x + 3 * key_step.x + 2 * key_row_offset + 10.0f, board_min.y + 3 * key_step.y + 10.0f);
23753 ImVec2 start_pos =
ImVec2(board_min.x + 5.0f - key_step.x, board_min.y);
23755 struct KeyLayoutData
23761 const KeyLayoutData keys_to_display[] = {
23762 {0, 0,
"", ImGuiKey_Tab}, {0, 1,
"Q", ImGuiKey_Q}, {0, 2,
"W", ImGuiKey_W},
23763 {0, 3,
"E", ImGuiKey_E}, {0, 4,
"R", ImGuiKey_R}, {1, 0,
"", ImGuiKey_CapsLock},
23764 {1, 1,
"A", ImGuiKey_A}, {1, 2,
"S", ImGuiKey_S}, {1, 3,
"D", ImGuiKey_D},
23765 {1, 4,
"F", ImGuiKey_F}, {2, 0,
"", ImGuiKey_LeftShift}, {2, 1,
"Z", ImGuiKey_Z},
23766 {2, 2,
"X", ImGuiKey_X}, {2, 3,
"C", ImGuiKey_C}, {2, 4,
"V", ImGuiKey_V}};
23771 Dummy(board_max - board_min);
23772 if (!IsItemVisible())
23774 draw_list->PushClipRect(board_min, board_max,
true);
23775 for (
int n = 0; n < IM_ARRAYSIZE(keys_to_display); n++)
23777 const KeyLayoutData *key_data = &keys_to_display[n];
23778 ImVec2 key_min =
ImVec2(start_pos.x + key_data->Col * key_step.x + key_data->Row * key_row_offset,
23779 start_pos.y + key_data->Row * key_step.y);
23780 ImVec2 key_max = key_min + key_size;
23781 draw_list->AddRectFilled(key_min, key_max, IM_COL32(204, 204, 204, 255), key_rounding);
23782 draw_list->AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding);
23783 ImVec2 face_min =
ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y);
23784 ImVec2 face_max =
ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y);
23785 draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, ImDrawFlags_None, 2.0f);
23786 draw_list->AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding);
23787 ImVec2 label_min =
ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y);
23788 draw_list->AddText(label_min, IM_COL32(64, 64, 64, 255), key_data->Label);
23790 draw_list->AddRectFilled(key_min, key_max, IM_COL32(255, 0, 0, 128), key_rounding);
23792 draw_list->PopClipRect();
23797void ImGui::DebugTextEncoding(
const char *str)
23799 Text(
"Text: \"%s\"", str);
23800 if (!BeginTable(
"##DebugTextEncoding", 4,
23801 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit |
23802 ImGuiTableFlags_Resizable))
23804 TableSetupColumn(
"Offset");
23805 TableSetupColumn(
"UTF-8");
23806 TableSetupColumn(
"Glyph");
23807 TableSetupColumn(
"Codepoint");
23809 for (
const char *p = str; *p != 0;)
23812 const int c_utf8_len = ImTextCharFromUtf8(&c, p, NULL);
23814 Text(
"%d", (
int)(p - str));
23816 for (
int byte_index = 0; byte_index < c_utf8_len; byte_index++)
23818 if (byte_index > 0)
23820 Text(
"0x%02X", (
int)(
unsigned char)p[byte_index]);
23823 if (GetFont()->FindGlyphNoFallback((ImWchar)c))
23824 TextUnformatted(p, p + c_utf8_len);
23826 TextUnformatted((c == IM_UNICODE_CODEPOINT_INVALID) ?
"[invalid]" :
"[missing]");
23828 Text(
"U+%04X", (
int)c);
23834static void DebugFlashStyleColorStop()
23837 if (g.DebugFlashStyleColorIdx != ImGuiCol_COUNT)
23838 g.Style.Colors[g.DebugFlashStyleColorIdx] = g.DebugFlashStyleColorBackup;
23839 g.DebugFlashStyleColorIdx = ImGuiCol_COUNT;
23843void ImGui::DebugFlashStyleColor(ImGuiCol idx)
23846 DebugFlashStyleColorStop();
23847 g.DebugFlashStyleColorTime = 0.5f;
23848 g.DebugFlashStyleColorIdx = idx;
23849 g.DebugFlashStyleColorBackup = g.Style.Colors[idx];
23852void ImGui::UpdateDebugToolFlashStyleColor()
23855 if (g.DebugFlashStyleColorTime <= 0.0f)
23857 ColorConvertHSVtoRGB(ImCos(g.DebugFlashStyleColorTime * 6.0f) * 0.5f + 0.5f, 0.5f, 0.5f,
23858 g.Style.Colors[g.DebugFlashStyleColorIdx].x, g.Style.Colors[g.DebugFlashStyleColorIdx].y,
23859 g.Style.Colors[g.DebugFlashStyleColorIdx].z);
23860 g.Style.Colors[g.DebugFlashStyleColorIdx].w = 1.0f;
23861 if ((g.DebugFlashStyleColorTime -= g.IO.DeltaTime) <= 0.0f)
23862 DebugFlashStyleColorStop();
23865static const char *FormatTextureIDForDebugDisplay(
char *buf,
int buf_size, ImTextureID tex_id)
23871 memcpy(&tex_id_opaque, &tex_id, ImMin(
sizeof(
void *),
sizeof(tex_id)));
23872 if (
sizeof(tex_id) >=
sizeof(
void *))
23873 ImFormatString(buf, buf_size,
"0x%p", tex_id_opaque.ptr);
23875 ImFormatString(buf, buf_size,
"0x%04X", tex_id_opaque.integer);
23880static void MetricsHelpMarker(
const char *desc)
23882 ImGui::TextDisabled(
"(?)");
23883 if (ImGui::BeginItemTooltip())
23885 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
23886 ImGui::TextUnformatted(desc);
23887 ImGui::PopTextWrapPos();
23888 ImGui::EndTooltip();
23895 for (
ImFont *font : atlas->Fonts)
23898 DebugNodeFont(font);
23901 if (TreeNode(
"Font Atlas",
"Font Atlas (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
23904 PushStyleVar(ImGuiStyleVar_ImageBorderSize, ImMax(1.0f, g.Style.ImageBorderSize));
23905 ImageWithBg(atlas->TexID,
ImVec2((
float)atlas->TexWidth, (
float)atlas->TexHeight),
ImVec2(0.0f, 0.0f),
23912void ImGui::ShowMetricsWindow(
bool *p_open)
23917 if (cfg->ShowDebugLog)
23918 ShowDebugLogWindow(&cfg->ShowDebugLog);
23919 if (cfg->ShowIDStackTool)
23920 ShowIDStackToolWindow(&cfg->ShowIDStackTool);
23922 if (!Begin(
"Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1)
23929 DebugBreakClearData();
23932 Text(
"Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
23933 if (g.ContextName[0] != 0)
23936 Text(
"(Context Name: \"%s\")", g.ContextName);
23938 Text(
"Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
23939 Text(
"%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices,
23940 io.MetricsRenderIndices / 3);
23941 Text(
"%d visible windows, %d current allocations", io.MetricsRenderWindows,
23942 g.DebugAllocInfo.TotalAllocCount - g.DebugAllocInfo.TotalFreeCount);
23951 WRT_OuterRectClipped,
23957 WRT_ContentRegionRect,
23960 const char *wrt_rects_names[WRT_Count] = {
"OuterRect",
"OuterRectClipped",
"InnerRect",
"InnerClipRect",
23961 "WorkRect",
"Content",
"ContentIdeal",
"ContentRegionRect"};
23969 TRT_BackgroundClipRect,
23971 TRT_ColumnsWorkRect,
23972 TRT_ColumnsClipRect,
23973 TRT_ColumnsContentHeadersUsed,
23974 TRT_ColumnsContentHeadersIdeal,
23975 TRT_ColumnsContentFrozen,
23976 TRT_ColumnsContentUnfrozen,
23979 const char *trt_rects_names[TRT_Count] = {
"OuterRect",
23984 "BackgroundClipRect",
23988 "ColumnsContentHeadersUsed",
23989 "ColumnsContentHeadersIdeal",
23990 "ColumnsContentFrozen",
23991 "ColumnsContentUnfrozen"};
23992 if (cfg->ShowWindowsRectsType < 0)
23993 cfg->ShowWindowsRectsType = WRT_WorkRect;
23994 if (cfg->ShowTablesRectsType < 0)
23995 cfg->ShowTablesRectsType = TRT_WorkRect;
24002 TableGetInstanceData(table, table->InstanceCurrent);
24003 if (rect_type == TRT_OuterRect)
24005 return table->OuterRect;
24007 else if (rect_type == TRT_InnerRect)
24009 return table->InnerRect;
24011 else if (rect_type == TRT_WorkRect)
24013 return table->WorkRect;
24015 else if (rect_type == TRT_HostClipRect)
24017 return table->HostClipRect;
24019 else if (rect_type == TRT_InnerClipRect)
24021 return table->InnerClipRect;
24023 else if (rect_type == TRT_BackgroundClipRect)
24025 return table->BgClipRect;
24027 else if (rect_type == TRT_ColumnsRect)
24030 return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX,
24031 table->InnerClipRect.Min.y + table_instance->LastOuterHeight);
24033 else if (rect_type == TRT_ColumnsWorkRect)
24036 return ImRect(c->WorkMinX, table->WorkRect.Min.y, c->WorkMaxX, table->WorkRect.Max.y);
24038 else if (rect_type == TRT_ColumnsClipRect)
24041 return c->ClipRect;
24043 else if (rect_type == TRT_ColumnsContentHeadersUsed)
24046 return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed,
24047 table->InnerClipRect.Min.y + table_instance->LastTopHeadersRowHeight);
24049 else if (rect_type == TRT_ColumnsContentHeadersIdeal)
24052 return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal,
24053 table->InnerClipRect.Min.y + table_instance->LastTopHeadersRowHeight);
24055 else if (rect_type == TRT_ColumnsContentFrozen)
24058 return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen,
24059 table->InnerClipRect.Min.y + table_instance->LastFrozenHeight);
24061 else if (rect_type == TRT_ColumnsContentUnfrozen)
24064 return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table_instance->LastFrozenHeight,
24065 c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y);
24073 if (rect_type == WRT_OuterRect)
24075 return window->Rect();
24077 else if (rect_type == WRT_OuterRectClipped)
24079 return window->OuterRectClipped;
24081 else if (rect_type == WRT_InnerRect)
24083 return window->InnerRect;
24085 else if (rect_type == WRT_InnerClipRect)
24087 return window->InnerClipRect;
24089 else if (rect_type == WRT_WorkRect)
24091 return window->WorkRect;
24093 else if (rect_type == WRT_Content)
24095 ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding;
24096 return ImRect(min, min + window->ContentSize);
24098 else if (rect_type == WRT_ContentIdeal)
24100 ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding;
24101 return ImRect(min, min + window->ContentSizeIdeal);
24103 else if (rect_type == WRT_ContentRegionRect)
24105 return window->ContentRegionRect;
24113 if (TreeNode(
"Tools"))
24118 SeparatorTextEx(0,
"Debug breaks", NULL, CalcTextSize(
"(?)").x + g.Style.SeparatorTextPadding.x);
24120 MetricsHelpMarker(
"Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a "
24121 "debugger attached, this will probably crash.");
24122 if (Checkbox(
"Show Item Picker", &g.DebugItemPickerActive) && g.DebugItemPickerActive)
24123 DebugStartItemPicker();
24124 Checkbox(
"Show \"Debug Break\" buttons in other sections (io.ConfigDebugIsDebuggerPresent)",
24125 &g.IO.ConfigDebugIsDebuggerPresent);
24127 SeparatorText(
"Visualize");
24129 Checkbox(
"Show Debug Log", &cfg->ShowDebugLog);
24131 MetricsHelpMarker(
"You can also call ImGui::ShowDebugLogWindow() from your code.");
24133 Checkbox(
"Show ID Stack Tool", &cfg->ShowIDStackTool);
24135 MetricsHelpMarker(
"You can also call ImGui::ShowIDStackToolWindow() from your code.");
24137 Checkbox(
"Show windows begin order", &cfg->ShowWindowsBeginOrder);
24138 Checkbox(
"Show windows rectangles", &cfg->ShowWindowsRects);
24140 SetNextItemWidth(GetFontSize() * 12);
24141 cfg->ShowWindowsRects |=
24142 Combo(
"##show_windows_rect_type", &cfg->ShowWindowsRectsType, wrt_rects_names, WRT_Count, WRT_Count);
24143 if (cfg->ShowWindowsRects && g.NavWindow != NULL)
24145 BulletText(
"'%s':", g.NavWindow->Name);
24147 for (
int rect_n = 0; rect_n < WRT_Count; rect_n++)
24149 ImRect r = Funcs::GetWindowRect(g.NavWindow, rect_n);
24150 Text(
"(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y,
24151 r.GetWidth(), r.GetHeight(), wrt_rects_names[rect_n]);
24156 Checkbox(
"Show tables rectangles", &cfg->ShowTablesRects);
24158 SetNextItemWidth(GetFontSize() * 12);
24159 cfg->ShowTablesRects |=
24160 Combo(
"##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count);
24161 if (cfg->ShowTablesRects && g.NavWindow != NULL)
24163 for (
int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++)
24165 ImGuiTable *table = g.Tables.TryGetMapData(table_n);
24166 if (table == NULL || table->LastFrameActive < g.FrameCount - 1 ||
24167 (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow))
24170 BulletText(
"Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount,
24171 table->OuterWindow->Name);
24172 if (IsItemHovered())
24173 GetForegroundDrawList()->AddRect(table->OuterRect.Min -
ImVec2(1, 1),
24174 table->OuterRect.Max +
ImVec2(1, 1), IM_COL32(255, 255, 0, 255),
24178 for (
int rect_n = 0; rect_n < TRT_Count; rect_n++)
24180 if (rect_n >= TRT_ColumnsRect)
24182 if (rect_n != TRT_ColumnsRect && rect_n != TRT_ColumnsClipRect)
24184 for (
int column_n = 0; column_n < table->ColumnsCount; column_n++)
24186 ImRect r = Funcs::GetTableRect(table, rect_n, column_n);
24187 ImFormatString(buf, IM_ARRAYSIZE(buf),
24188 "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y,
24189 r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n,
24190 trt_rects_names[rect_n]);
24192 if (IsItemHovered())
24193 GetForegroundDrawList()->AddRect(r.Min -
ImVec2(1, 1), r.Max +
ImVec2(1, 1),
24194 IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
24199 ImRect r = Funcs::GetTableRect(table, rect_n, -1);
24200 ImFormatString(buf, IM_ARRAYSIZE(buf),
"(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s",
24201 r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(),
24202 trt_rects_names[rect_n]);
24204 if (IsItemHovered())
24205 GetForegroundDrawList()->AddRect(r.Min -
ImVec2(1, 1), r.Max +
ImVec2(1, 1),
24206 IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
24213 "Show groups rectangles",
24214 &g.DebugShowGroupRects);
24216 SeparatorText(
"Validate");
24218 Checkbox(
"Debug Begin/BeginChild return value", &io.ConfigDebugBeginReturnValueLoop);
24220 MetricsHelpMarker(
"Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths "
24221 "then repeat. Windows should be flickering while running.");
24223 Checkbox(
"UTF-8 Encoding viewer", &cfg->ShowTextEncodingViewer);
24225 MetricsHelpMarker(
"You can also call ImGui::DebugTextEncoding() from your code with a given string to test "
24226 "that your UTF-8 encoding settings are correct.");
24227 if (cfg->ShowTextEncodingViewer)
24229 static char buf[64] =
"";
24230 SetNextItemWidth(-FLT_MIN);
24231 InputText(
"##DebugTextEncodingBuf", buf, IM_ARRAYSIZE(buf));
24233 DebugTextEncoding(buf);
24240 if (TreeNode(
"Windows",
"Windows (%d)", g.Windows.Size))
24243 DebugNodeWindowsList(&g.Windows,
"By display order");
24244 DebugNodeWindowsList(&g.WindowsFocusOrder,
"By focus order (root windows)");
24245 if (TreeNode(
"By submission order (begin stack)"))
24250 temp_buffer.resize(0);
24252 if (window->LastFrameActive + 1 >= g.FrameCount)
24253 temp_buffer.push_back(window);
24256 static int IMGUI_CDECL WindowComparerByBeginOrder(
const void *lhs,
const void *rhs)
24258 return ((
int)(*(
const ImGuiWindow *
const *)lhs)->BeginOrderWithinContext -
24259 (*(
const ImGuiWindow *
const *)rhs)->BeginOrderWithinContext);
24262 ImQsort(temp_buffer.Data, (
size_t)temp_buffer.Size,
sizeof(
ImGuiWindow *),
24263 Func::WindowComparerByBeginOrder);
24264 DebugNodeWindowsListByBeginStackParent(temp_buffer.Data, temp_buffer.Size, NULL);
24272 int drawlist_count = 0;
24274 drawlist_count += viewport->DrawDataP.CmdLists.Size;
24275 if (TreeNode(
"DrawLists",
"DrawLists (%d)", drawlist_count))
24277 Checkbox(
"Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh);
24278 Checkbox(
"Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes);
24281 bool viewport_has_drawlist =
false;
24282 for (
ImDrawList *draw_list : viewport->DrawDataP.CmdLists)
24284 if (!viewport_has_drawlist)
24285 Text(
"Active DrawLists in Viewport #%d, ID: 0x%08X", viewport->Idx, viewport->ID);
24286 viewport_has_drawlist =
true;
24287 DebugNodeDrawList(NULL, viewport, draw_list,
"DrawList");
24294 if (TreeNode(
"Viewports",
"Viewports (%d)", g.Viewports.Size))
24296 cfg->HighlightMonitorIdx = -1;
24297 bool open = TreeNode(
"Monitors",
"Monitors (%d)", g.PlatformIO.Monitors.Size);
24299 MetricsHelpMarker(
"Dear ImGui uses monitor data:\n- to query DPI settings on a per monitor basis\n- to "
24300 "position popup/tooltips so they don't straddle monitors.");
24303 for (
int i = 0; i < g.PlatformIO.Monitors.Size; i++)
24305 DebugNodePlatformMonitor(&g.PlatformIO.Monitors[i],
"Monitor", i);
24306 if (IsItemHovered())
24307 cfg->HighlightMonitorIdx = i;
24309 DebugNodePlatformMonitor(&g.FallbackMonitor,
"Fallback", 0);
24313 SetNextItemOpen(
true, ImGuiCond_Once);
24314 if (TreeNode(
"Windows Minimap"))
24316 RenderViewportsThumbnails();
24319 cfg->HighlightViewportID = 0;
24321 BulletText(
"MouseViewport: 0x%08X (UserHovered 0x%08X, LastHovered 0x%08X)",
24322 g.MouseViewport ? g.MouseViewport->ID : 0, g.IO.MouseHoveredViewport,
24323 g.MouseLastHoveredViewport ? g.MouseLastHoveredViewport->ID : 0);
24324 if (TreeNode(
"Inferred Z order (front-to-back)"))
24327 viewports.resize(g.Viewports.Size);
24328 memcpy(viewports.Data, g.Viewports.Data, g.Viewports.size_in_bytes());
24329 if (viewports.Size > 1)
24330 ImQsort(viewports.Data, viewports.Size,
sizeof(
ImGuiViewport *),
24331 ViewportComparerByLastFocusedStampCount);
24334 BulletText(
"Viewport #%d, ID: 0x%08X, LastFocused = %08d, PlatformFocused = %s, Window: \"%s\"",
24335 viewport->Idx, viewport->ID, viewport->LastFocusedStampCount,
24336 (g.PlatformIO.Platform_GetWindowFocus && viewport->PlatformWindowCreated)
24337 ? (g.PlatformIO.Platform_GetWindowFocus(viewport) ?
"1" :
"0")
24339 viewport->Window ? viewport->Window->Name :
"N/A");
24340 if (IsItemHovered())
24341 cfg->HighlightViewportID = viewport->ID;
24347 DebugNodeViewport(viewport);
24352 if (TreeNode(
"Popups",
"Popups (%d)", g.OpenPopupStack.Size))
24358 BulletText(
"PopupID: %08x, Window: '%s' (%s%s), RestoreNavWindow '%s', ParentWindow '%s'",
24359 popup_data.PopupId, window ? window->Name :
"NULL",
24360 window && (window->Flags & ImGuiWindowFlags_ChildWindow) ?
"Child;" :
"",
24361 window && (window->Flags & ImGuiWindowFlags_ChildMenu) ?
"Menu;" :
"",
24362 popup_data.RestoreNavWindow ? popup_data.RestoreNavWindow->Name :
"NULL",
24363 window && window->ParentWindow ? window->ParentWindow->Name :
"NULL");
24369 if (TreeNode(
"TabBars",
"Tab Bars (%d)", g.TabBars.GetAliveCount()))
24371 for (
int n = 0; n < g.TabBars.GetMapSize(); n++)
24372 if (
ImGuiTabBar *tab_bar = g.TabBars.TryGetMapData(n))
24375 DebugNodeTabBar(tab_bar,
"TabBar");
24382 if (TreeNode(
"Tables",
"Tables (%d)", g.Tables.GetAliveCount()))
24384 for (
int n = 0; n < g.Tables.GetMapSize(); n++)
24385 if (
ImGuiTable *table = g.Tables.TryGetMapData(n))
24386 DebugNodeTable(table);
24392 if (TreeNode(
"Fonts",
"Fonts (%d)", atlas->Fonts.Size))
24394 ShowFontAtlas(atlas);
24399 if (TreeNode(
"InputText"))
24401 DebugNodeInputTextState(&g.InputTextState);
24406 if (TreeNode(
"TypingSelect",
"TypingSelect (%d)", g.TypingSelectState.SearchBuffer[0] != 0 ? 1 : 0))
24408 DebugNodeTypingSelectState(&g.TypingSelectState);
24413 if (TreeNode(
"MultiSelect",
"MultiSelect (%d)", g.MultiSelectStorage.GetAliveCount()))
24416 BulletText(
"BoxSelect ID=0x%08X, Starting = %d, Active %d", bs->ID, bs->IsStarting, bs->IsActive);
24417 for (
int n = 0; n < g.MultiSelectStorage.GetMapSize(); n++)
24419 DebugNodeMultiSelectState(state);
24424#ifdef IMGUI_HAS_DOCK
24425 if (TreeNode(
"Docking"))
24427 static bool root_nodes_only =
true;
24429 Checkbox(
"List root nodes", &root_nodes_only);
24430 Checkbox(
"Ctrl shows window dock info", &cfg->ShowDockingNodes);
24431 if (SmallButton(
"Clear nodes"))
24433 DockContextClearNodes(&g, 0,
true);
24436 if (SmallButton(
"Rebuild all"))
24438 dc->WantFullRebuild =
true;
24440 for (
int n = 0; n < dc->Nodes.Data.Size; n++)
24442 if (!root_nodes_only || node->IsRootNode())
24443 DebugNodeDockNode(node,
"Node");
24449 if (TreeNode(
"Settings"))
24451 if (SmallButton(
"Clear"))
24452 ClearIniSettings();
24454 if (SmallButton(
"Save to memory"))
24455 SaveIniSettingsToMemory();
24457 if (SmallButton(
"Save to disk"))
24458 SaveIniSettingsToDisk(g.IO.IniFilename);
24460 if (g.IO.IniFilename)
24461 Text(
"\"%s\"", g.IO.IniFilename);
24463 TextUnformatted(
"<NULL>");
24464 Checkbox(
"io.ConfigDebugIniSettings", &io.ConfigDebugIniSettings);
24465 Text(
"SettingsDirtyTimer %.2f", g.SettingsDirtyTimer);
24466 if (TreeNode(
"SettingsHandlers",
"Settings handlers: (%d)", g.SettingsHandlers.Size))
24469 BulletText(
"\"%s\"", handler.TypeName);
24472 if (TreeNode(
"SettingsWindows",
"Settings packed data: Windows: %d bytes", g.SettingsWindows.size()))
24475 settings = g.SettingsWindows.next_chunk(settings))
24476 DebugNodeWindowSettings(settings);
24480 if (TreeNode(
"SettingsTables",
"Settings packed data: Tables: %d bytes", g.SettingsTables.size()))
24483 settings = g.SettingsTables.next_chunk(settings))
24484 DebugNodeTableSettings(settings);
24488#ifdef IMGUI_HAS_DOCK
24489 if (TreeNode(
"SettingsDocking",
"Settings packed data: Docking"))
24492 Text(
"In SettingsWindows:");
24494 settings = g.SettingsWindows.next_chunk(settings))
24495 if (settings->DockId != 0)
24496 BulletText(
"Window '%s' -> DockId %08X DockOrder=%d", settings->GetName(), settings->DockId,
24497 settings->DockOrder);
24498 Text(
"In SettingsNodes:");
24499 for (
int n = 0; n < dc->NodesSettings.Size; n++)
24502 const char *selected_tab_name = NULL;
24503 if (settings->SelectedTabId)
24505 if (
ImGuiWindow *window = FindWindowByID(settings->SelectedTabId))
24506 selected_tab_name = window->Name;
24507 else if (
ImGuiWindowSettings *window_settings = FindWindowSettingsByID(settings->SelectedTabId))
24508 selected_tab_name = window_settings->GetName();
24510 BulletText(
"Node %08X, Parent %08X, SelectedTab %08X ('%s')", settings->ID, settings->ParentNodeId,
24511 settings->SelectedTabId,
24512 selected_tab_name ? selected_tab_name
24513 : settings->SelectedTabId ?
"N/A"
24520 if (TreeNode(
"SettingsIniData",
"Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size()))
24522 InputTextMultiline(
"##Ini", (
char *)(
void *)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size,
24523 ImVec2(-FLT_MIN, GetTextLineHeight() * 20), ImGuiInputTextFlags_ReadOnly);
24530 if (TreeNode(
"Memory allocations"))
24533 Text(
"%d current allocations", info->TotalAllocCount - info->TotalFreeCount);
24534 if (SmallButton(
"GC now"))
24536 g.GcCompactAll =
true;
24538 Text(
"Recent frames with allocations:");
24539 int buf_size = IM_ARRAYSIZE(info->LastEntriesBuf);
24540 for (
int n = buf_size - 1; n >= 0; n--)
24542 ImGuiDebugAllocEntry *entry = &info->LastEntriesBuf[(info->LastEntriesIdx - n + buf_size) % buf_size];
24543 BulletText(
"Frame %06d: %+3d ( %2d alloc, %2d free )", entry->FrameCount,
24544 entry->AllocCount - entry->FreeCount, entry->AllocCount, entry->FreeCount);
24548 Text(
"<- %d frames ago", g.FrameCount - entry->FrameCount);
24554 if (TreeNode(
"Inputs"))
24556 Text(
"KEYBOARD/GAMEPAD/MOUSE KEYS");
24561 Text(
"Keys down:");
24562 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
24567 Text(IsNamedKey(key) ?
"\"%s\"" :
"\"%s\" %d", GetKeyName(key), key);
24569 Text(
"(%.02f)", GetKeyData(key)->DownDuration);
24571 Text(
"Keys pressed:");
24572 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
24577 Text(IsNamedKey(key) ?
"\"%s\"" :
"\"%s\" %d", GetKeyName(key), key);
24579 Text(
"Keys released:");
24580 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
24585 Text(IsNamedKey(key) ?
"\"%s\"" :
"\"%s\" %d", GetKeyName(key), key);
24587 Text(
"Keys mods: %s%s%s%s", io.KeyCtrl ?
"CTRL " :
"", io.KeyShift ?
"SHIFT " :
"", io.KeyAlt ?
"ALT " :
"",
24588 io.KeySuper ?
"SUPER " :
"");
24589 Text(
"Chars queue:");
24590 for (
int i = 0; i < io.InputQueueCharacters.Size; i++)
24592 ImWchar c = io.InputQueueCharacters[i];
24594 Text(
"\'%c\' (0x%04X)", (c >
' ' && c <= 255) ? (
char)c :
'?', c);
24596 DebugRenderKeyboardPreview(GetWindowDrawList());
24600 Text(
"MOUSE STATE");
24603 if (IsMousePosValid())
24604 Text(
"Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
24606 Text(
"Mouse pos: <INVALID>");
24607 Text(
"Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
24608 int count = IM_ARRAYSIZE(io.MouseDown);
24609 Text(
"Mouse down:");
24610 for (
int i = 0; i < count; i++)
24611 if (IsMouseDown(i))
24614 Text(
"b%d (%.02f secs)", i, io.MouseDownDuration[i]);
24616 Text(
"Mouse clicked:");
24617 for (
int i = 0; i < count; i++)
24618 if (IsMouseClicked(i))
24621 Text(
"b%d (%d)", i, io.MouseClickedCount[i]);
24623 Text(
"Mouse released:");
24624 for (
int i = 0; i < count; i++)
24625 if (IsMouseReleased(i))
24630 Text(
"Mouse wheel: %.1f", io.MouseWheel);
24631 Text(
"MouseStationaryTimer: %.2f", g.MouseStationaryTimer);
24632 Text(
"Mouse source: %s", GetMouseSourceName(io.MouseSource));
24633 Text(
"Pen Pressure: %.1f", io.PenPressure);
24637 Text(
"MOUSE WHEELING");
24640 Text(
"WheelingWindow: '%s'", g.WheelingWindow ? g.WheelingWindow->Name :
"NULL");
24641 Text(
"WheelingWindowReleaseTimer: %.2f", g.WheelingWindowReleaseTimer);
24642 Text(
"WheelingAxisAvg[] = { %.3f, %.3f }, Main Axis: %s", g.WheelingAxisAvg.x, g.WheelingAxisAvg.y,
24643 (g.WheelingAxisAvg.x > g.WheelingAxisAvg.y) ?
"X"
24644 : (g.WheelingAxisAvg.x < g.WheelingAxisAvg.y) ?
"Y"
24649 Text(
"KEY OWNERS");
24652 if (BeginChild(
"##owners",
ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8),
24653 ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings))
24654 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
24657 if (owner_data->OwnerCurr == ImGuiKeyOwner_NoOwner)
24659 Text(
"%s: 0x%08X%s", GetKeyName(key), owner_data->OwnerCurr,
24660 owner_data->LockUntilRelease ?
" LockUntilRelease"
24661 : owner_data->LockThisFrame ?
" LockThisFrame"
24663 DebugLocateItemOnHover(owner_data->OwnerCurr);
24668 Text(
"SHORTCUT ROUTING");
24670 MetricsHelpMarker(
"Declared shortcut routes automatically set key owner when mods matches.");
24673 if (BeginChild(
"##routes",
ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8),
24674 ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings))
24675 for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
24678 for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1;)
24681 ImGuiKeyChord key_chord = key | routing_data->Mods;
24682 Text(
"%s: 0x%08X (scored %d)", GetKeyChordName(key_chord), routing_data->RoutingCurr,
24683 routing_data->RoutingCurrScore);
24684 DebugLocateItemOnHover(routing_data->RoutingCurr);
24685 if (g.IO.ConfigDebugIsDebuggerPresent)
24688 if (DebugBreakButton(
"**DebugBreak**",
"in SetShortcutRouting() for this KeyChord"))
24689 g.DebugBreakInShortcutRouting = key_chord;
24691 idx = routing_data->NextEntryIndex;
24695 Text(
"(ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: 0x%X)", g.ActiveIdUsingAllKeyboardKeys,
24696 g.ActiveIdUsingNavDirMask);
24702 if (TreeNode(
"Internal state"))
24706 Text(
"HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name :
"NULL");
24707 Text(
"HoveredWindow->Root: '%s'", g.HoveredWindow ? g.HoveredWindow->RootWindowDockTree->Name :
"NULL");
24708 Text(
"HoveredWindowUnderMovingWindow: '%s'",
24709 g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name :
"NULL");
24710 Text(
"HoveredDockNode: 0x%08X", g.DebugHoveredDockNode ? g.DebugHoveredDockNode->ID : 0);
24711 Text(
"MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name :
"NULL");
24712 Text(
"MouseViewport: 0x%08X (UserHovered 0x%08X, LastHovered 0x%08X)", g.MouseViewport->ID,
24713 g.IO.MouseHoveredViewport, g.MouseLastHoveredViewport ? g.MouseLastHoveredViewport->ID : 0);
24718 Text(
"ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame,
24719 g.ActiveIdTimer, g.ActiveIdAllowOverlap, GetInputSourceName(g.ActiveIdSource));
24720 DebugLocateItemOnHover(g.ActiveId);
24721 Text(
"ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name :
"NULL");
24722 Text(
"ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: %X", g.ActiveIdUsingAllKeyboardKeys,
24723 g.ActiveIdUsingNavDirMask);
24724 Text(
"HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer,
24725 g.HoveredIdAllowOverlap);
24726 Text(
"HoverItemDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f", g.HoverItemDelayId, g.HoverItemDelayTimer,
24727 g.HoverItemDelayClearTimer);
24728 Text(
"DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId,
24729 g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
24730 DebugLocateItemOnHover(g.DragDropPayload.SourceId);
24735 Text(
"NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name :
"NULL");
24736 Text(
"NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer);
24737 DebugLocateItemOnHover(g.NavId);
24738 Text(
"NavInputSource: %s", GetInputSourceName(g.NavInputSource));
24739 Text(
"NavLastValidSelectionUserData = %" IM_PRId64
" (0x%" IM_PRIX64
")", g.NavLastValidSelectionUserData,
24740 g.NavLastValidSelectionUserData);
24741 Text(
"NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
24742 Text(
"NavActivateId/DownId/PressedId: %08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId,
24743 g.NavActivatePressedId);
24744 Text(
"NavActivateFlags: %04X", g.NavActivateFlags);
24745 Text(
"NavCursorVisible: %d, NavHighlightItemUnderNav: %d", g.NavCursorVisible, g.NavHighlightItemUnderNav);
24746 Text(
"NavFocusScopeId = 0x%08X", g.NavFocusScopeId);
24747 Text(
"NavFocusRoute[] = ");
24748 for (
int path_n = g.NavFocusRoute.Size - 1; path_n >= 0; path_n--)
24751 SameLine(0.0f, 0.0f);
24752 Text(
"0x%08X/", focus_scope.ID);
24753 SetItemTooltip(
"In window \"%s\"", FindWindowByID(focus_scope.WindowID)->Name);
24755 Text(
"NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name :
"NULL");
24762 if (cfg->ShowWindowsRects || cfg->ShowWindowsBeginOrder)
24766 if (!window->WasActive)
24768 ImDrawList *draw_list = GetForegroundDrawList(window);
24769 if (cfg->ShowWindowsRects)
24771 ImRect r = Funcs::GetWindowRect(window, cfg->ShowWindowsRectsType);
24772 draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
24774 if (cfg->ShowWindowsBeginOrder && !(window->Flags & ImGuiWindowFlags_ChildWindow))
24777 ImFormatString(buf, IM_ARRAYSIZE(buf),
"%d", window->BeginOrderWithinContext);
24778 float font_size = GetFontSize();
24779 draw_list->AddRectFilled(window->Pos, window->Pos +
ImVec2(font_size, font_size),
24780 IM_COL32(200, 100, 100, 255));
24781 draw_list->AddText(window->Pos, IM_COL32(255, 255, 255, 255), buf);
24787 if (cfg->ShowTablesRects)
24789 for (
int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++)
24791 ImGuiTable *table = g.Tables.TryGetMapData(table_n);
24792 if (table == NULL || table->LastFrameActive < g.FrameCount - 1)
24794 ImDrawList *draw_list = GetForegroundDrawList(table->OuterWindow);
24795 if (cfg->ShowTablesRectsType >= TRT_ColumnsRect)
24797 for (
int column_n = 0; column_n < table->ColumnsCount; column_n++)
24799 ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
24800 ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255)
24801 : IM_COL32(255, 0, 128, 255);
24802 float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
24803 draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness);
24808 ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, -1);
24809 draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
24814#ifdef IMGUI_HAS_DOCK
24816 if (cfg->ShowDockingNodes && g.IO.KeyCtrl && g.DebugHoveredDockNode)
24822 node->HostWindow ? GetForegroundDrawList(node->HostWindow) : GetForegroundDrawList(GetMainViewport());
24823 p += ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"DockId: %X%s\n", node->ID,
24824 node->IsCentralNode() ?
" *CentralNode*" :
"");
24825 p += ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"WindowClass: %08X\n", node->WindowClass.ClassId);
24826 p += ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"Size: (%.0f, %.0f)\n", node->Size.x, node->Size.y);
24828 ImFormatString(p, buf + IM_ARRAYSIZE(buf) - p,
"SizeRef: (%.0f, %.0f)\n", node->SizeRef.x, node->SizeRef.y);
24829 int depth = DockNodeGetDepth(node);
24830 overlay_draw_list->AddRect(node->Pos +
ImVec2(3, 3) * (
float)depth,
24831 node->Pos + node->Size -
ImVec2(3, 3) * (
float)depth, IM_COL32(200, 100, 100, 255));
24833 overlay_draw_list->AddRectFilled(pos -
ImVec2(1, 1), pos + CalcTextSize(buf) +
ImVec2(1, 1),
24834 IM_COL32(200, 100, 100, 255));
24835 overlay_draw_list->AddText(NULL, 0.0f, pos, IM_COL32(255, 255, 255, 255), buf);
24842void ImGui::DebugBreakClearData()
24846 g.DebugBreakInWindow = 0;
24847 g.DebugBreakInTable = 0;
24848 g.DebugBreakInShortcutRouting = ImGuiKey_None;
24851void ImGui::DebugBreakButtonTooltip(
bool keyboard_only,
const char *description_of_location)
24853 if (!BeginItemTooltip())
24855 Text(
"To call IM_DEBUG_BREAK() %s:", description_of_location);
24857 TextUnformatted(keyboard_only ?
"- Press 'Pause/Break' on keyboard."
24858 :
"- Press 'Pause/Break' on keyboard.\n- or Click (may alter focus/active id).\n- or "
24859 "navigate using keyboard and press space.");
24861 TextUnformatted(
"Choose one way that doesn't interfere with what you are trying to debug!\nYou need a debugger "
24862 "attached or this will crash!");
24868bool ImGui::DebugBreakButton(
const char *label,
const char *description_of_location)
24871 if (window->SkipItems)
24875 const ImGuiID
id = window->GetID(label);
24876 const ImVec2 label_size = CalcTextSize(label, NULL,
true);
24877 ImVec2 pos = window->DC.CursorPos +
ImVec2(0.0f, window->DC.CurrLineTextBaseOffset);
24878 ImVec2 size =
ImVec2(label_size.x + g.Style.FramePadding.x * 2.0f, label_size.y);
24880 const ImRect bb(pos, pos + size);
24881 ItemSize(size, 0.0f);
24882 if (!ItemAdd(bb,
id))
24886 bool hovered = ItemHoverable(bb,
id, g.CurrentItemFlags);
24887 bool pressed = hovered && (IsKeyChordPressed(g.DebugBreakKeyChord) || IsMouseClicked(0) || g.NavActivateId == id);
24888 DebugBreakButtonTooltip(
false, description_of_location);
24890 ImVec4 col4f = GetStyleColorVec4(hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
24892 ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z, hsv.x, hsv.y, hsv.z);
24893 ColorConvertHSVtoRGB(hsv.x + 0.20f, hsv.y, hsv.z, col4f.x, col4f.y, col4f.z);
24895 RenderNavCursor(bb,
id);
24896 RenderFrame(bb.Min, bb.Max, GetColorU32(col4f),
true, g.Style.FrameRounding);
24897 RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size, g.Style.ButtonTextAlign, &bb);
24899 IMGUI_TEST_ENGINE_ITEM_INFO(
id, label, g.LastItemData.StatusFlags);
24906 if (!TreeNode((
void *)(uintptr_t)columns->ID,
"Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID,
24907 columns->Count, columns->Flags))
24909 BulletText(
"Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX,
24912 BulletText(
"Column %02d: OffsetNorm %.3f (= %.1f px)", (int)columns->Columns.index_from_ptr(&column),
24913 column.OffsetNorm, GetColumnOffsetFromNorm(columns, column.OffsetNorm));
24917static void DebugNodeDockNodeFlags(ImGuiDockNodeFlags *p_flags,
const char *label,
bool enabled)
24919 using namespace ImGui;
24921 PushStyleVar(ImGuiStyleVar_FramePadding,
ImVec2(0.0f, 0.0f));
24922 Text(
"%s:", label);
24925 CheckboxFlags(
"NoResize", p_flags, ImGuiDockNodeFlags_NoResize);
24926 CheckboxFlags(
"NoResizeX", p_flags, ImGuiDockNodeFlags_NoResizeX);
24927 CheckboxFlags(
"NoResizeY", p_flags, ImGuiDockNodeFlags_NoResizeY);
24928 CheckboxFlags(
"NoTabBar", p_flags, ImGuiDockNodeFlags_NoTabBar);
24929 CheckboxFlags(
"HiddenTabBar", p_flags, ImGuiDockNodeFlags_HiddenTabBar);
24930 CheckboxFlags(
"NoWindowMenuButton", p_flags, ImGuiDockNodeFlags_NoWindowMenuButton);
24931 CheckboxFlags(
"NoCloseButton", p_flags, ImGuiDockNodeFlags_NoCloseButton);
24932 CheckboxFlags(
"DockedWindowsInFocusRoute", p_flags, ImGuiDockNodeFlags_DockedWindowsInFocusRoute);
24933 CheckboxFlags(
"NoDocking", p_flags, ImGuiDockNodeFlags_NoDocking);
24934 CheckboxFlags(
"NoDockingSplit", p_flags, ImGuiDockNodeFlags_NoDockingSplit);
24935 CheckboxFlags(
"NoDockingSplitOther", p_flags, ImGuiDockNodeFlags_NoDockingSplitOther);
24936 CheckboxFlags(
"NoDockingOver", p_flags, ImGuiDockNodeFlags_NoDockingOverMe);
24937 CheckboxFlags(
"NoDockingOverOther", p_flags, ImGuiDockNodeFlags_NoDockingOverOther);
24938 CheckboxFlags(
"NoDockingOverEmpty", p_flags, ImGuiDockNodeFlags_NoDockingOverEmpty);
24939 CheckboxFlags(
"NoUndocking", p_flags, ImGuiDockNodeFlags_NoUndocking);
24947void ImGui::DebugNodeDockNode(
ImGuiDockNode *node,
const char *label)
24950 const bool is_alive = (g.FrameCount - node->LastFrameAlive < 2);
24951 const bool is_active = (g.FrameCount - node->LastFrameActive < 2);
24954 PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled));
24957 ImGuiTreeNodeFlags tree_node_flags = node->IsFocused ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None;
24958 if (node->Windows.Size > 0)
24959 open = TreeNodeEx((
void *)(intptr_t)node->ID, tree_node_flags,
"%s 0x%04X%s: %d windows (vis: '%s')", label,
24960 node->ID, node->IsVisible ?
"" :
" (hidden)", node->Windows.Size,
24961 node->VisibleWindow ? node->VisibleWindow->Name :
"NULL");
24963 open = TreeNodeEx((
void *)(intptr_t)node->ID, tree_node_flags,
"%s 0x%04X%s: %s (vis: '%s')", label, node->ID,
24964 node->IsVisible ?
"" :
" (hidden)",
24965 (node->SplitAxis == ImGuiAxis_X) ?
"horizontal split"
24966 : (node->SplitAxis == ImGuiAxis_Y) ?
"vertical split"
24968 node->VisibleWindow ? node->VisibleWindow->Name :
"NULL");
24973 if (is_active && IsItemHovered())
24974 if (
ImGuiWindow *window = node->HostWindow ? node->HostWindow : node->VisibleWindow)
24975 GetForegroundDrawList(window)->AddRect(node->Pos, node->Pos + node->Size, IM_COL32(255, 255, 0, 255));
24978 IM_ASSERT(node->ChildNodes[0] == NULL || node->ChildNodes[0]->ParentNode == node);
24979 IM_ASSERT(node->ChildNodes[1] == NULL || node->ChildNodes[1]->ParentNode == node);
24980 BulletText(
"Pos (%.0f,%.0f), Size (%.0f, %.0f) Ref (%.0f, %.0f)", node->Pos.x, node->Pos.y, node->Size.x,
24981 node->Size.y, node->SizeRef.x, node->SizeRef.y);
24982 DebugNodeWindow(node->HostWindow,
"HostWindow");
24983 DebugNodeWindow(node->VisibleWindow,
"VisibleWindow");
24984 BulletText(
"SelectedTabID: 0x%08X, LastFocusedNodeID: 0x%08X", node->SelectedTabId, node->LastFocusedNodeId);
24985 BulletText(
"Misc:%s%s%s%s%s%s%s", node->IsDockSpace() ?
" IsDockSpace" :
"",
24986 node->IsCentralNode() ?
" IsCentralNode" :
"", is_alive ?
" IsAlive" :
"",
24987 is_active ?
" IsActive" :
"", node->IsFocused ?
" IsFocused" :
"",
24988 node->WantLockSizeOnce ?
" WantLockSizeOnce" :
"",
24989 node->HasCentralNodeChild ?
" HasCentralNodeChild" :
"");
24990 if (TreeNode(
"flags",
"Flags Merged: 0x%04X, Local: 0x%04X, InWindows: 0x%04X, Shared: 0x%04X",
24991 node->MergedFlags, node->LocalFlags, node->LocalFlagsInWindows, node->SharedFlags))
24993 if (BeginTable(
"flags", 4))
24996 DebugNodeDockNodeFlags(&node->MergedFlags,
"MergedFlags",
false);
24998 DebugNodeDockNodeFlags(&node->LocalFlags,
"LocalFlags",
true);
25000 DebugNodeDockNodeFlags(&node->LocalFlagsInWindows,
"LocalFlagsInWindows",
false);
25002 DebugNodeDockNodeFlags(&node->SharedFlags,
"SharedFlags",
true);
25007 if (node->ParentNode)
25008 DebugNodeDockNode(node->ParentNode,
"ParentNode");
25009 if (node->ChildNodes[0])
25010 DebugNodeDockNode(node->ChildNodes[0],
"Child[0]");
25011 if (node->ChildNodes[1])
25012 DebugNodeDockNode(node->ChildNodes[1],
"Child[1]");
25014 DebugNodeTabBar(node->TabBar,
"TabBar");
25015 DebugNodeWindowsList(&node->Windows,
"Windows");
25029 int cmd_count = draw_list->CmdBuffer.Size;
25030 if (cmd_count > 0 && draw_list->CmdBuffer.back().ElemCount == 0 && draw_list->CmdBuffer.back().UserCallback == NULL)
25032 bool node_open = TreeNode(draw_list,
"%s: '%s' %d vtx, %d indices, %d cmds", label,
25033 draw_list->_OwnerName ? draw_list->_OwnerName :
"", draw_list->VtxBuffer.Size,
25034 draw_list->IdxBuffer.Size, cmd_count);
25035 if (draw_list == GetWindowDrawList())
25038 TextColored(
ImVec4(1.0f, 0.4f, 0.4f, 1.0f),
"CURRENTLY APPENDING");
25046 viewport ? GetForegroundDrawList(viewport) : NULL;
25047 if (window && IsItemHovered() && fg_draw_list)
25048 fg_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
25052 if (window && !window->WasActive)
25053 TextDisabled(
"Warning: owning Window is inactive. This DrawList is not being rendered!");
25055 for (
const ImDrawCmd *pcmd = draw_list->CmdBuffer.Data; pcmd < draw_list->CmdBuffer.Data + cmd_count; pcmd++)
25057 if (pcmd->UserCallback)
25059 BulletText(
"Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData);
25063 char texid_desc[20];
25064 FormatTextureIDForDebugDisplay(texid_desc, IM_ARRAYSIZE(texid_desc), pcmd->TextureId);
25066 ImFormatString(buf, IM_ARRAYSIZE(buf),
"DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
25067 pcmd->ElemCount / 3, texid_desc, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z,
25069 bool pcmd_node_open = TreeNode((
void *)(pcmd - draw_list->CmdBuffer.begin()),
"%s", buf);
25070 if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list)
25071 DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg->ShowDrawCmdMesh,
25072 cfg->ShowDrawCmdBoundingBoxes);
25073 if (!pcmd_node_open)
25078 const ImDrawIdx *idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
25079 const ImDrawVert *vtx_buffer = draw_list->VtxBuffer.Data + pcmd->VtxOffset;
25080 float total_area = 0.0f;
25081 for (
unsigned int idx_n = pcmd->IdxOffset; idx_n < pcmd->IdxOffset + pcmd->ElemCount;)
25084 for (
int n = 0; n < 3; n++, idx_n++)
25085 triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos;
25086 total_area += ImTriangleArea(triangle[0], triangle[1], triangle[2]);
25090 ImFormatString(buf, IM_ARRAYSIZE(buf),
"Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px",
25091 pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area);
25093 if (IsItemHovered() && fg_draw_list)
25094 DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd,
true,
false);
25098 clipper.Begin(pcmd->ElemCount / 3);
25100 while (clipper.Step())
25101 for (
int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3;
25102 prim < clipper.DisplayEnd; prim++)
25104 char *buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf);
25106 for (
int n = 0; n < 3; n++, idx_i++)
25108 const ImDrawVert &v = vtx_buffer[idx_buffer ? idx_buffer[idx_i] : idx_i];
25109 triangle[n] = v.pos;
25111 ImFormatString(buf_p, buf_end - buf_p,
"%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n",
25112 (n == 0) ?
"Vert:" :
" ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
25115 Selectable(buf,
false);
25116 if (fg_draw_list && IsItemHovered())
25118 ImDrawListFlags backup_flags = fg_draw_list->Flags;
25119 fg_draw_list->Flags &=
25120 ~ImDrawListFlags_AntiAliasedLines;
25122 fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
25123 fg_draw_list->Flags = backup_flags;
25132void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(
ImDrawList *out_draw_list,
const ImDrawList *draw_list,
25133 const ImDrawCmd *draw_cmd,
bool show_mesh,
bool show_aabb)
25135 IM_ASSERT(show_mesh || show_aabb);
25138 ImRect clip_rect = draw_cmd->ClipRect;
25139 ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
25140 ImDrawListFlags backup_flags = out_draw_list->Flags;
25141 out_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines;
25143 for (
unsigned int idx_n = draw_cmd->IdxOffset, idx_end = draw_cmd->IdxOffset + draw_cmd->ElemCount;
25146 ImDrawIdx *idx_buffer = (draw_list->IdxBuffer.Size > 0)
25147 ? draw_list->IdxBuffer.Data
25150 ImDrawVert *vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset;
25153 for (
int n = 0; n < 3; n++, idx_n++)
25154 vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
25156 out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed,
25162 out_draw_list->AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max),
25163 IM_COL32(255, 0, 255, 255));
25164 out_draw_list->AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max),
25165 IM_COL32(0, 255, 255, 255));
25167 out_draw_list->Flags = backup_flags;
25171void ImGui::DebugNodeFont(
ImFont *font)
25174 TreeNode(font,
"Font: \"%s\": %.2f px, %d glyphs, %d sources(s)", font->Sources ? font->Sources[0].Name :
"",
25175 font->FontSize, font->Glyphs.Size, font->SourcesCount);
25182 Text(
"The quick brown fox jumps over the lazy dog");
25190 if (SmallButton(
"Set as default"))
25191 GetIO().FontDefault = font;
25194 SetNextItemWidth(GetFontSize() * 8);
25195 DragFloat(
"Font scale", &font->Scale, 0.005f, 0.3f, 2.0f,
"%.1f");
25198 "Note that the default embedded font is NOT meant to be scaled.\n\n"
25199 "Font are currently rendered into bitmaps at a given size at the time of building the atlas. "
25200 "You may oversample them to get some flexibility with scaling. "
25201 "You can also render at multiple sizes and select which one to use at runtime.\n\n"
25202 "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");
25203 Text(
"Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
25205 Text(
"Fallback character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar);
25206 Text(
"Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar);
25207 const int surface_sqrt = (int)ImSqrt((
float)font->MetricsTotalSurface);
25208 Text(
"Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);
25209 for (
int config_i = 0; config_i < font->SourcesCount; config_i++)
25213 int oversample_h, oversample_v;
25214 ImFontAtlasBuildGetOversampleFactors(src, &oversample_h, &oversample_v);
25215 BulletText(
"Input %d: \'%s\', Oversample: (%d=>%d,%d=>%d), PixelSnapH: %d, Offset: (%.1f,%.1f)", config_i,
25216 src->Name, src->OversampleH, oversample_h, src->OversampleV, oversample_v, src->PixelSnapH,
25217 src->GlyphOffset.x, src->GlyphOffset.y);
25222 if (TreeNode(
"Glyphs",
"Glyphs (%d)", font->Glyphs.Size))
25224 ImDrawList *draw_list = GetWindowDrawList();
25225 const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);
25226 const float cell_size = font->FontSize * 1;
25227 const float cell_spacing = GetStyle().ItemSpacing.y;
25228 for (
unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
25233 if (!(base & 8191) && font->IsGlyphRangeUnused(base, base + 8191))
25235 base += 8192 - 256;
25240 for (
unsigned int n = 0; n < 256; n++)
25241 if (font->FindGlyphNoFallback((ImWchar)(base + n)))
25245 if (!TreeNode((
void *)(intptr_t)base,
"U+%04X..U+%04X (%d %s)", base, base + 255, count,
25246 count > 1 ?
"glyphs" :
"glyph"))
25250 ImVec2 base_pos = GetCursorScreenPos();
25251 for (
unsigned int n = 0; n < 256; n++)
25255 ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing),
25256 base_pos.y + (n / 16) * (cell_size + cell_spacing));
25257 ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
25258 const ImFontGlyph *glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
25259 draw_list->AddRect(cell_p1, cell_p2,
25260 glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
25263 font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
25264 if (IsMouseHoveringRect(cell_p1, cell_p2) && BeginTooltip())
25266 DebugNodeFontGlyph(font, glyph);
25270 Dummy(
ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
25282 Text(
"Codepoint: U+%04X", glyph->Codepoint);
25284 Text(
"Visible: %d", glyph->Visible);
25285 Text(
"AdvanceX: %.1f", glyph->AdvanceX);
25286 Text(
"Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
25287 Text(
"UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
25291void ImGui::DebugNodeStorage(
ImGuiStorage *storage,
const char *label)
25293 if (!TreeNode(label,
"%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes()))
25297 BulletText(
"Key 0x%08X Value { i: %d }", p.key,
25299 DebugLocateItemOnHover(p.key);
25305void ImGui::DebugNodeTabBar(
ImGuiTabBar *tab_bar,
const char *label)
25310 const char *buf_end = buf + IM_ARRAYSIZE(buf);
25311 const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2);
25312 p += ImFormatString(p, buf_end - p,
"%s 0x%08X (%d tabs)%s {", label, tab_bar->ID, tab_bar->Tabs.Size,
25313 is_active ?
"" :
" *Inactive*");
25314 for (
int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++)
25317 p += ImFormatString(p, buf_end - p,
"%s'%s'", tab_n > 0 ?
", " :
"", TabBarGetTabName(tab_bar, tab));
25319 p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ?
" ... }" :
" } ");
25322 PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled));
25324 bool open = TreeNode(label,
"%s", buf);
25329 if (is_active && IsItemHovered())
25331 ImDrawList *draw_list = GetForegroundDrawList();
25332 draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255));
25333 draw_list->AddLine(
ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y),
25334 ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
25335 draw_list->AddLine(
ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y),
25336 ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
25340 for (
int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
25344 if (SmallButton(
"<"))
25346 TabBarQueueReorder(tab_bar, tab, -1);
25349 if (SmallButton(
">"))
25351 TabBarQueueReorder(tab_bar, tab, +1);
25354 Text(
"%02d%c Tab 0x%08X '%s' Offset: %.2f, Width: %.2f/%.2f", tab_n,
25355 (tab->ID == tab_bar->SelectedTabId) ?
'*' :
' ', tab->ID, TabBarGetTabName(tab_bar, tab), tab->Offset,
25356 tab->Width, tab->ContentWidth);
25366 SetNextItemOpen(
true, ImGuiCond_Once);
25367 bool open = TreeNode((
void *)(intptr_t)viewport->ID,
"Viewport #%d, ID: 0x%08X, Parent: 0x%08X, Window: \"%s\"",
25368 viewport->Idx, viewport->ID, viewport->ParentViewportId,
25369 viewport->Window ? viewport->Window->Name :
"N/A");
25370 if (IsItemHovered())
25371 g.DebugMetricsConfig.HighlightViewportID = viewport->ID;
25374 ImGuiWindowFlags flags = viewport->Flags;
25375 BulletText(
"Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Inset Left: %.0f Top: %.0f, Right: %.0f, "
25376 "Bottom: %.0f\nMonitor: %d, DpiScale: %.0f%%",
25377 viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y, viewport->WorkInsetMin.x,
25378 viewport->WorkInsetMin.y, viewport->WorkInsetMax.x, viewport->WorkInsetMax.y,
25379 viewport->PlatformMonitor, viewport->DpiScale * 100.0f);
25380 if (viewport->Idx > 0)
25383 if (SmallButton(
"Reset Pos"))
25385 viewport->Pos =
ImVec2(200, 200);
25386 viewport->UpdateWorkRect();
25387 if (viewport->Window)
25388 viewport->Window->Pos = viewport->Pos;
25391 BulletText(
"Flags: 0x%04X =%s%s%s%s%s%s%s%s%s%s%s%s%s", viewport->Flags,
25394 (flags & ImGuiViewportFlags_IsPlatformMonitor) ?
" IsPlatformMonitor" :
"",
25395 (flags & ImGuiViewportFlags_IsMinimized) ?
" IsMinimized" :
"",
25396 (flags & ImGuiViewportFlags_IsFocused) ?
" IsFocused" :
"",
25397 (flags & ImGuiViewportFlags_OwnedByApp) ?
" OwnedByApp" :
"",
25398 (flags & ImGuiViewportFlags_NoDecoration) ?
" NoDecoration" :
"",
25399 (flags & ImGuiViewportFlags_NoTaskBarIcon) ?
" NoTaskBarIcon" :
"",
25400 (flags & ImGuiViewportFlags_NoFocusOnAppearing) ?
" NoFocusOnAppearing" :
"",
25401 (flags & ImGuiViewportFlags_NoFocusOnClick) ?
" NoFocusOnClick" :
"",
25402 (flags & ImGuiViewportFlags_NoInputs) ?
" NoInputs" :
"",
25403 (flags & ImGuiViewportFlags_NoRendererClear) ?
" NoRendererClear" :
"",
25404 (flags & ImGuiViewportFlags_NoAutoMerge) ?
" NoAutoMerge" :
"",
25405 (flags & ImGuiViewportFlags_TopMost) ?
" TopMost" :
"",
25406 (flags & ImGuiViewportFlags_CanHostOtherWindows) ?
" CanHostOtherWindows" :
"");
25407 for (
ImDrawList *draw_list : viewport->DrawDataP.CmdLists)
25408 DebugNodeDrawList(NULL, viewport, draw_list,
"DrawList");
25413void ImGui::DebugNodePlatformMonitor(
ImGuiPlatformMonitor *monitor,
const char *label,
int idx)
25415 BulletText(
"%s %d: DPI %.0f%%\n MainMin (%.0f,%.0f), MainMax (%.0f,%.0f), MainSize (%.0f,%.0f)\n WorkMin "
25416 "(%.0f,%.0f), WorkMax (%.0f,%.0f), WorkSize (%.0f,%.0f)",
25417 label, idx, monitor->DpiScale * 100.0f, monitor->MainPos.x, monitor->MainPos.y,
25418 monitor->MainPos.x + monitor->MainSize.x, monitor->MainPos.y + monitor->MainSize.y, monitor->MainSize.x,
25419 monitor->MainSize.y, monitor->WorkPos.x, monitor->WorkPos.y, monitor->WorkPos.x + monitor->WorkSize.x,
25420 monitor->WorkPos.y + monitor->WorkSize.y, monitor->WorkSize.x, monitor->WorkSize.y);
25423void ImGui::DebugNodeWindow(
ImGuiWindow *window,
const char *label)
25425 if (window == NULL)
25427 BulletText(
"%s: NULL", label);
25432 const bool is_active = window->WasActive;
25433 ImGuiTreeNodeFlags tree_node_flags =
25434 (window == g.NavWindow) ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None;
25437 PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled));
25440 TreeNodeEx(label, tree_node_flags,
"%s '%s'%s", label, window->Name, is_active ?
"" :
" *Inactive*");
25445 if (IsItemHovered() && is_active)
25446 GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
25450 if (window->MemoryCompacted)
25451 TextDisabled(
"Note: some memory buffers have been compacted/freed.");
25453 if (g.IO.ConfigDebugIsDebuggerPresent && DebugBreakButton(
"**DebugBreak**",
"in Begin()"))
25454 g.DebugBreakInWindow = window->ID;
25456 ImGuiWindowFlags flags = window->Flags;
25457 DebugNodeDrawList(window, window->Viewport, window->DrawList,
"DrawList");
25458 BulletText(
"Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f) Ideal (%.1f,%.1f)", window->Pos.x,
25459 window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y,
25460 window->ContentSizeIdeal.x, window->ContentSizeIdeal.y);
25461 BulletText(
"Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags, (flags & ImGuiWindowFlags_ChildWindow) ?
"Child " :
"",
25462 (flags & ImGuiWindowFlags_Tooltip) ?
"Tooltip " :
"", (flags & ImGuiWindowFlags_Popup) ?
"Popup " :
"",
25463 (flags & ImGuiWindowFlags_Modal) ?
"Modal " :
"",
25464 (flags & ImGuiWindowFlags_ChildMenu) ?
"ChildMenu " :
"",
25465 (flags & ImGuiWindowFlags_NoSavedSettings) ?
"NoSavedSettings " :
"",
25466 (flags & ImGuiWindowFlags_NoMouseInputs) ?
"NoMouseInputs" :
"",
25467 (flags & ImGuiWindowFlags_NoNavInputs) ?
"NoNavInputs" :
"",
25468 (flags & ImGuiWindowFlags_AlwaysAutoResize) ?
"AlwaysAutoResize" :
"");
25469 if (flags & ImGuiWindowFlags_ChildWindow)
25470 BulletText(
"ChildFlags: 0x%08X (%s%s%s%s..)", window->ChildFlags,
25471 (window->ChildFlags & ImGuiChildFlags_Borders) ?
"Borders " :
"",
25472 (window->ChildFlags & ImGuiChildFlags_ResizeX) ?
"ResizeX " :
"",
25473 (window->ChildFlags & ImGuiChildFlags_ResizeY) ?
"ResizeY " :
"",
25474 (window->ChildFlags & ImGuiChildFlags_NavFlattened) ?
"NavFlattened " :
"");
25475 BulletText(
"WindowClassId: 0x%08X", window->WindowClass.ClassId);
25476 BulletText(
"Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y,
25477 window->ScrollMax.y, window->ScrollbarX ?
"X" :
"", window->ScrollbarY ?
"Y" :
"");
25478 BulletText(
"Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive,
25479 window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
25480 BulletText(
"Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden,
25481 window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems);
25482 for (
int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
25484 ImRect r = window->NavRectRel[layer];
25485 if (r.Min.x >= r.Max.x && r.Min.y >= r.Max.y)
25486 BulletText(
"NavLastIds[%d]: 0x%08X", layer, window->NavLastIds[layer]);
25488 BulletText(
"NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window->NavLastIds[layer], r.Min.x,
25489 r.Min.y, r.Max.x, r.Max.y);
25490 DebugLocateItemOnHover(window->NavLastIds[layer]);
25492 const ImVec2 *pr = window->NavPreferredScoringPosRel;
25493 for (
int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
25494 BulletText(
"NavPreferredScoringPosRel[%d] = {%.1f,%.1f)", layer,
25495 (pr[layer].x == FLT_MAX ? -99999.0f : pr[layer].x),
25496 (pr[layer].y == FLT_MAX ? -99999.0f : pr[layer].y));
25497 BulletText(
"NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window->DC.NavLayersActiveMask,
25498 window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name :
"NULL");
25500 BulletText(
"Viewport: %d%s, ViewportId: 0x%08X, ViewportPos: (%.1f,%.1f)",
25501 window->Viewport ? window->Viewport->Idx : -1, window->ViewportOwned ?
" (Owned)" :
"",
25502 window->ViewportId, window->ViewportPos.x, window->ViewportPos.y);
25503 BulletText(
"ViewportMonitor: %d", window->Viewport ? window->Viewport->PlatformMonitor : -1);
25504 BulletText(
"DockId: 0x%04X, DockOrder: %d, Act: %d, Vis: %d", window->DockId, window->DockOrder,
25505 window->DockIsActive, window->DockTabIsVisible);
25506 if (window->DockNode || window->DockNodeAsHost)
25507 DebugNodeDockNode(window->DockNodeAsHost ? window->DockNodeAsHost : window->DockNode,
25508 window->DockNodeAsHost ?
"DockNodeAsHost" :
"DockNode");
25510 if (window->RootWindow != window)
25512 DebugNodeWindow(window->RootWindow,
"RootWindow");
25514 if (window->RootWindowDockTree != window->RootWindow)
25516 DebugNodeWindow(window->RootWindowDockTree,
"RootWindowDockTree");
25518 if (window->ParentWindow != NULL)
25520 DebugNodeWindow(window->ParentWindow,
"ParentWindow");
25522 if (window->ParentWindowForFocusRoute != NULL)
25524 DebugNodeWindow(window->ParentWindowForFocusRoute,
"ParentWindowForFocusRoute");
25526 if (window->DC.ChildWindows.Size > 0)
25528 DebugNodeWindowsList(&window->DC.ChildWindows,
"ChildWindows");
25530 if (window->ColumnsStorage.Size > 0 && TreeNode(
"Columns",
"Columns sets (%d)", window->ColumnsStorage.Size))
25533 DebugNodeColumns(&columns);
25536 DebugNodeStorage(&window->StateStorage,
"Storage");
25542 if (settings->WantDelete)
25544 Text(
"0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d", settings->ID, settings->GetName(), settings->Pos.x,
25545 settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed);
25546 if (settings->WantDelete)
25552 if (!TreeNode(label,
"%s (%d)", label, windows->Size))
25554 for (
int i = windows->Size - 1; i >= 0; i--)
25556 PushID((*windows)[i]);
25557 DebugNodeWindow((*windows)[i],
"Window");
25564void ImGui::DebugNodeWindowsListByBeginStackParent(
ImGuiWindow **windows,
int windows_size,
25567 for (
int i = 0; i < windows_size; i++)
25570 if (window->ParentWindowInBeginStack != parent_in_begin_stack)
25573 ImFormatString(buf, IM_ARRAYSIZE(buf),
"[%04d] Window", window->BeginOrderWithinContext);
25575 DebugNodeWindow(window, buf);
25577 DebugNodeWindowsListByBeginStackParent(windows + i + 1, windows_size - i - 1, window);
25586void ImGui::DebugLog(
const char *fmt, ...)
25589 va_start(args, fmt);
25590 DebugLogV(fmt, args);
25594void ImGui::DebugLogV(
const char *fmt, va_list args)
25597 const int old_size = g.DebugLogBuf.size();
25598 if (g.ContextName[0] != 0)
25599 g.DebugLogBuf.appendf(
"[%s] [%05d] ", g.ContextName, g.FrameCount);
25601 g.DebugLogBuf.appendf(
"[%05d] ", g.FrameCount);
25602 g.DebugLogBuf.appendfv(fmt, args);
25603 g.DebugLogIndex.append(g.DebugLogBuf.c_str(), old_size, g.DebugLogBuf.size());
25604 if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY)
25605 IMGUI_DEBUG_PRINTF(
"%s", g.DebugLogBuf.begin() + old_size);
25606#ifdef IMGUI_ENABLE_TEST_ENGINE
25608 const int new_size = g.DebugLogBuf.size();
25609 const bool trailing_carriage_return = (g.DebugLogBuf[new_size - 1] ==
'\n');
25610 if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTestEngine)
25611 IMGUI_TEST_ENGINE_LOG(
"%.*s", new_size - old_size - (trailing_carriage_return ? 1 : 0),
25612 g.DebugLogBuf.begin() + old_size);
25617static void SameLineOrWrap(
const ImVec2 &size)
25621 ImVec2 pos(window->DC.CursorPosPrevLine.x + g.Style.ItemSpacing.x, window->DC.CursorPosPrevLine.y);
25622 if (window->WorkRect.Contains(
ImRect(pos, pos + size)))
25626static void ShowDebugLogFlag(
const char *name, ImGuiDebugLogFlags flags)
25629 ImVec2 size(ImGui::GetFrameHeight() + g.Style.ItemInnerSpacing.x + ImGui::CalcTextSize(name).x,
25630 ImGui::GetFrameHeight());
25631 SameLineOrWrap(size);
25633 bool highlight_errors = (flags == ImGuiDebugLogFlags_EventError && g.DebugLogSkippedErrors > 0);
25634 if (highlight_errors)
25635 ImGui::PushStyleColor(ImGuiCol_Text,
25636 ImLerp(g.Style.Colors[ImGuiCol_Text],
ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.30f));
25637 if (ImGui::CheckboxFlags(name, &g.DebugLogFlags, flags) && g.IO.KeyShift && (g.DebugLogFlags & flags) != 0)
25639 g.DebugLogAutoDisableFrames = 2;
25640 g.DebugLogAutoDisableFlags |= flags;
25642 if (highlight_errors)
25644 ImGui::PopStyleColor();
25645 ImGui::SetItemTooltip(
"%d past errors skipped.", g.DebugLogSkippedErrors);
25649 ImGui::SetItemTooltip(
"Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)");
25653void ImGui::ShowDebugLogWindow(
bool *p_open)
25656 if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) == 0)
25657 SetNextWindowSize(
ImVec2(0.0f, GetFontSize() * 12.0f), ImGuiCond_FirstUseEver);
25658 if (!Begin(
"Dear ImGui Debug Log", p_open) || GetCurrentWindow()->BeginCount > 1)
25664 ImGuiDebugLogFlags all_enable_flags = ImGuiDebugLogFlags_EventMask_ & ~ImGuiDebugLogFlags_EventInputRouting;
25665 CheckboxFlags(
"All", &g.DebugLogFlags, all_enable_flags);
25666 SetItemTooltip(
"(except InputRouting which is spammy)");
25668 ShowDebugLogFlag(
"Errors", ImGuiDebugLogFlags_EventError);
25669 ShowDebugLogFlag(
"ActiveId", ImGuiDebugLogFlags_EventActiveId);
25670 ShowDebugLogFlag(
"Clipper", ImGuiDebugLogFlags_EventClipper);
25671 ShowDebugLogFlag(
"Docking", ImGuiDebugLogFlags_EventDocking);
25672 ShowDebugLogFlag(
"Focus", ImGuiDebugLogFlags_EventFocus);
25673 ShowDebugLogFlag(
"IO", ImGuiDebugLogFlags_EventIO);
25675 ShowDebugLogFlag(
"Nav", ImGuiDebugLogFlags_EventNav);
25676 ShowDebugLogFlag(
"Popup", ImGuiDebugLogFlags_EventPopup);
25677 ShowDebugLogFlag(
"Selection", ImGuiDebugLogFlags_EventSelection);
25678 ShowDebugLogFlag(
"Viewport", ImGuiDebugLogFlags_EventViewport);
25679 ShowDebugLogFlag(
"InputRouting", ImGuiDebugLogFlags_EventInputRouting);
25681 if (SmallButton(
"Clear"))
25683 g.DebugLogBuf.clear();
25684 g.DebugLogIndex.clear();
25685 g.DebugLogSkippedErrors = 0;
25688 if (SmallButton(
"Copy"))
25689 SetClipboardText(g.DebugLogBuf.c_str());
25691 if (SmallButton(
"Configure Outputs.."))
25692 OpenPopup(
"Outputs");
25693 if (BeginPopup(
"Outputs"))
25695 CheckboxFlags(
"OutputToTTY", &g.DebugLogFlags, ImGuiDebugLogFlags_OutputToTTY);
25696#ifndef IMGUI_ENABLE_TEST_ENGINE
25699 CheckboxFlags(
"OutputToTestEngine", &g.DebugLogFlags, ImGuiDebugLogFlags_OutputToTestEngine);
25700#ifndef IMGUI_ENABLE_TEST_ENGINE
25706 BeginChild(
"##log",
ImVec2(0.0f, 0.0f), ImGuiChildFlags_Borders,
25707 ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
25709 const ImGuiDebugLogFlags backup_log_flags = g.DebugLogFlags;
25710 g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper;
25713 clipper.Begin(g.DebugLogIndex.size());
25714 while (clipper.Step())
25715 for (
int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
25716 DebugTextUnformattedWithLocateItem(g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no),
25717 g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no));
25718 g.DebugLogFlags = backup_log_flags;
25719 if (GetScrollY() >= GetScrollMaxY())
25720 SetScrollHereY(1.0f);
25727void ImGui::DebugTextUnformattedWithLocateItem(
const char *line_begin,
const char *line_end)
25729 TextUnformatted(line_begin, line_end);
25730 if (!IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
25733 ImRect text_rect = g.LastItemData.Rect;
25734 for (
const char *p = line_begin; p <= line_end - 10; p++)
25737 if (p[0] !=
'0' || (p[1] !=
'x' && p[1] !=
'X') || sscanf(p + 2,
"%X", &
id) != 1 || ImCharIsXdigitA(p[10]))
25739 ImVec2 p0 = CalcTextSize(line_begin, p);
25740 ImVec2 p1 = CalcTextSize(p, p + 10);
25741 g.LastItemData.Rect =
ImRect(text_rect.Min +
ImVec2(p0.x, 0.0f), text_rect.Min +
ImVec2(p0.x + p1.x, p1.y));
25742 if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max,
true))
25743 DebugLocateItemOnHover(
id);
25753void ImGui::DebugDrawCursorPos(ImU32 col)
25757 ImVec2 pos = window->DC.CursorPos;
25758 window->DrawList->AddLine(
ImVec2(pos.x, pos.y - 3.0f),
ImVec2(pos.x, pos.y + 4.0f), col, 1.0f);
25759 window->DrawList->AddLine(
ImVec2(pos.x - 3.0f, pos.y),
ImVec2(pos.x + 4.0f, pos.y), col, 1.0f);
25763void ImGui::DebugDrawLineExtents(ImU32 col)
25767 float curr_x = window->DC.CursorPos.x;
25768 float line_y1 = (window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y);
25769 float line_y2 = line_y1 + (window->DC.IsSameLine ? window->DC.PrevLineSize.y : window->DC.CurrLineSize.y);
25770 window->DrawList->AddLine(
ImVec2(curr_x - 5.0f, line_y1),
ImVec2(curr_x + 5.0f, line_y1), col, 1.0f);
25771 window->DrawList->AddLine(
ImVec2(curr_x - 0.5f, line_y1),
ImVec2(curr_x - 0.5f, line_y2), col, 1.0f);
25772 window->DrawList->AddLine(
ImVec2(curr_x - 5.0f, line_y2),
ImVec2(curr_x + 5.0f, line_y2), col, 1.0f);
25776void ImGui::DebugDrawItemRect(ImU32 col)
25780 GetForegroundDrawList(window)->AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col);
25784static const ImU32 DEBUG_LOCATE_ITEM_COLOR = IM_COL32(0, 255, 0, 255);
25786void ImGui::DebugLocateItem(ImGuiID target_id)
25789 g.DebugLocateId = target_id;
25790 g.DebugLocateFrames = 2;
25791 g.DebugBreakInLocateId =
false;
25795void ImGui::DebugLocateItemOnHover(ImGuiID target_id)
25797 if (target_id == 0 ||
25798 !IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenBlockedByPopup))
25801 DebugLocateItem(target_id);
25802 GetForegroundDrawList(g.CurrentWindow)
25803 ->AddRect(g.LastItemData.Rect.Min -
ImVec2(3.0f, 3.0f), g.LastItemData.Rect.Max +
ImVec2(3.0f, 3.0f),
25804 DEBUG_LOCATE_ITEM_COLOR);
25807 if (g.IO.ConfigDebugIsDebuggerPresent && g.MouseStationaryTimer > 1.0f)
25809 DebugBreakButtonTooltip(
false,
"in ItemAdd()");
25810 if (IsKeyChordPressed(g.DebugBreakKeyChord))
25811 g.DebugBreakInLocateId =
true;
25815void ImGui::DebugLocateItemResolveWithLastItem()
25820 if (g.DebugBreakInLocateId)
25824 g.DebugLocateId = 0;
25825 ImDrawList *draw_list = GetForegroundDrawList(g.CurrentWindow);
25826 ImRect r = item_data.Rect;
25828 ImVec2 p1 = g.IO.MousePos;
25830 : (p1.x > r.Max.x) ? r.Max.x
25832 (p1.y < r.Min.y) ? r.Min.y
25833 : (p1.y > r.Max.y) ? r.Max.y
25835 draw_list->AddRect(r.Min, r.Max, DEBUG_LOCATE_ITEM_COLOR);
25836 draw_list->AddLine(p1, p2, DEBUG_LOCATE_ITEM_COLOR);
25839void ImGui::DebugStartItemPicker()
25842 g.DebugItemPickerActive =
true;
25847void ImGui::UpdateDebugToolItemPicker()
25850 g.DebugItemPickerBreakId = 0;
25851 if (!g.DebugItemPickerActive)
25854 const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
25857 g.DebugItemPickerActive =
false;
25858 const bool change_mapping = g.IO.KeyMods == (ImGuiMod_Ctrl | ImGuiMod_Shift);
25859 if (!change_mapping && IsMouseClicked(g.DebugItemPickerMouseButton) && hovered_id)
25861 g.DebugItemPickerBreakId = hovered_id;
25862 g.DebugItemPickerActive =
false;
25864 for (
int mouse_button = 0; mouse_button < 3; mouse_button++)
25865 if (change_mapping && IsMouseClicked(mouse_button))
25866 g.DebugItemPickerMouseButton = (ImU8)mouse_button;
25867 SetNextWindowBgAlpha(0.70f);
25868 if (!BeginTooltip())
25870 Text(
"HoveredId: 0x%08X", hovered_id);
25871 Text(
"Press ESC to abort picking.");
25872 const char *mouse_button_names[] = {
"Left",
"Right",
"Middle"};
25873 if (change_mapping)
25874 Text(
"Remap w/ Ctrl+Shift: click anywhere to select new mouse button.");
25876 TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled),
25877 "Click %s Button to break in debugger! (remap w/ Ctrl+Shift)",
25878 mouse_button_names[g.DebugItemPickerMouseButton]);
25883void ImGui::UpdateDebugToolStackQueries()
25889 g.DebugHookIdInfo = 0;
25890 if (g.FrameCount != tool->LastActiveFrame + 1)
25896 const ImGuiID query_id = g.HoveredIdPreviousFrame ? g.HoveredIdPreviousFrame : g.ActiveId;
25897 if (tool->QueryId != query_id)
25899 tool->QueryId = query_id;
25900 tool->StackLevel = -1;
25901 tool->Results.resize(0);
25907 int stack_level = tool->StackLevel;
25908 if (stack_level >= 0 && stack_level < tool->Results.Size)
25909 if (tool->Results[stack_level].QuerySuccess || tool->Results[stack_level].QueryFrameCount > 2)
25910 tool->StackLevel++;
25913 stack_level = tool->StackLevel;
25914 if (stack_level == -1)
25915 g.DebugHookIdInfo = query_id;
25916 if (stack_level >= 0 && stack_level < tool->Results.Size)
25918 g.DebugHookIdInfo = tool->Results[stack_level].ID;
25919 tool->Results[stack_level].QueryFrameCount++;
25924void ImGui::DebugHookIdInfo(ImGuiID
id, ImGuiDataType data_type,
const void *data_id,
const void *data_id_end)
25932 if (tool->StackLevel == -1)
25934 tool->StackLevel++;
25936 for (
int n = 0; n < window->IDStack.Size + 1; n++)
25937 tool->Results[n].ID = (n < window->IDStack.Size) ? window->IDStack[n] : id;
25942 IM_ASSERT(tool->StackLevel >= 0);
25943 if (tool->StackLevel != window->IDStack.Size)
25946 IM_ASSERT(info->ID ==
id && info->QueryFrameCount > 0);
25950 case ImGuiDataType_S32:
25951 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"%d", (
int)(intptr_t)data_id);
25953 case ImGuiDataType_String:
25954 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"%.*s",
25955 data_id_end ? (
int)((
const char *)data_id_end - (
const char *)data_id)
25956 : (int)ImStrlen((const char *)data_id),
25957 (const char *)data_id);
25959 case ImGuiDataType_Pointer:
25960 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"(void*)0x%p", data_id);
25962 case ImGuiDataType_ID:
25963 if (info->Desc[0] != 0)
25966 ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc),
"0x%08X [override]",
id);
25971 info->QuerySuccess =
true;
25972 info->DataType = data_type;
25975static int StackToolFormatLevelInfo(
ImGuiIDStackTool *tool,
int n,
bool format_for_ui,
char *buf,
size_t buf_size)
25978 ImGuiWindow *window = (info->Desc[0] == 0 && n == 0) ? ImGui::FindWindowByID(info->ID) : NULL;
25980 return ImFormatString(buf, buf_size, format_for_ui ?
"\"%s\" [window]" :
"%s", window->Name);
25981 if (info->QuerySuccess)
25983 return ImFormatString(buf, buf_size,
25984 (format_for_ui && info->DataType == ImGuiDataType_String) ?
"\"%s\"" :
"%s", info->Desc);
25985 if (tool->StackLevel < tool->Results.Size)
25988#ifdef IMGUI_ENABLE_TEST_ENGINE
25989 if (
const char *label =
25990 ImGuiTestEngine_FindItemDebugLabel(GImGui, info->ID))
25991 return ImFormatString(buf, buf_size, format_for_ui ?
"??? \"%s\"" :
"%s", label);
25993 return ImFormatString(buf, buf_size,
"???");
25997void ImGui::ShowIDStackToolWindow(
bool *p_open)
26000 if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) == 0)
26001 SetNextWindowSize(
ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver);
26002 if (!Begin(
"Dear ImGui ID Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1)
26012 tool->ResultPathBuf.resize(0);
26013 for (
int stack_n = 0; stack_n < tool->Results.Size; stack_n++)
26015 char level_desc[256];
26016 StackToolFormatLevelInfo(tool, stack_n,
false, level_desc, IM_ARRAYSIZE(level_desc));
26017 tool->ResultPathBuf.append(stack_n == 0 ?
"//" :
"/");
26018 for (
int n = 0; level_desc[n]; n++)
26020 if (level_desc[n] ==
'/')
26021 tool->ResultPathBuf.append(
"\\");
26022 tool->ResultPathBuf.append(level_desc + n, level_desc + n + 1);
26025 Text(
"0x%08X", tool->QueryId);
26028 "Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level "
26029 "of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID "
26030 "of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details.");
26033 const float time_since_copy = (float)g.Time - tool->CopyToClipboardLastTime;
26035 PushStyleVarY(ImGuiStyleVar_FramePadding, 0.0f);
26036 Checkbox(
"Ctrl+C: copy path", &tool->CopyToClipboardOnCtrlC);
26039 TextColored((time_since_copy >= 0.0f && time_since_copy < 0.75f && ImFmod(time_since_copy, 0.25f) < 0.25f * 0.5f)
26040 ?
ImVec4(1.f, 1.f, 0.3f, 1.f)
26043 if (tool->CopyToClipboardOnCtrlC &&
26044 Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused))
26046 tool->CopyToClipboardLastTime = (float)g.Time;
26047 SetClipboardText(tool->ResultPathBuf.c_str());
26050 Text(
"- Path \"%s\"", tool->ResultPathBuf.c_str());
26051#ifdef IMGUI_ENABLE_TEST_ENGINE
26052 Text(
"- Label \"%s\"", tool->QueryId ? ImGuiTestEngine_FindItemDebugLabel(&g, tool->QueryId) :
"");
26058 tool->LastActiveFrame = g.FrameCount;
26059 if (tool->Results.Size > 0 && BeginTable(
"##table", 3, ImGuiTableFlags_Borders))
26061 const float id_width = CalcTextSize(
"0xDDDDDDDD").x;
26062 TableSetupColumn(
"Seed", ImGuiTableColumnFlags_WidthFixed, id_width);
26063 TableSetupColumn(
"PushID", ImGuiTableColumnFlags_WidthStretch);
26064 TableSetupColumn(
"Result", ImGuiTableColumnFlags_WidthFixed, id_width);
26066 for (
int n = 0; n < tool->Results.Size; n++)
26070 Text(
"0x%08X", (n > 0) ? tool->Results[n - 1].ID : 0);
26072 StackToolFormatLevelInfo(tool, n,
true, g.TempBuffer.Data, g.TempBuffer.Size);
26073 TextUnformatted(g.TempBuffer.Data);
26075 Text(
"0x%08X", info->ID);
26076 if (n == tool->Results.Size - 1)
26077 TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_Header));
26086void ImGui::ShowMetricsWindow(
bool *)
26101void ImGui::DebugNodeFont(
ImFont *)
26104void ImGui::DebugNodeStorage(
ImGuiStorage *,
const char *)
26107void ImGui::DebugNodeTabBar(
ImGuiTabBar *,
const char *)
26110void ImGui::DebugNodeWindow(
ImGuiWindow *,
const char *)
26123void ImGui::ShowDebugLogWindow(
bool *)
26126void ImGui::ShowIDStackToolWindow(
bool *)
26129void ImGui::DebugStartItemPicker()
26132void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType,
const void *,
const void *)
26143#ifdef IMGUI_INCLUDE_IMGUI_USER_INL
26144#include "imgui_user.inl"